Debugger: Added "Devleoper Mode" option to give faster access to all debugging tools

This commit is contained in:
Souryo 2017-08-14 23:44:01 -04:00
parent 02edb4558f
commit 5f47b402b5
27 changed files with 597 additions and 293 deletions

View File

@ -404,13 +404,13 @@ void Console::Run()
_runLock.Release();
PlatformUtilities::EnableScreensaver();
while(paused && !_stop && _debugger == nullptr) {
while(paused && !_stop && (!_debugger || !_debugger->CheckFlag(DebuggerFlags::DebuggerWindowEnabled))) {
//Sleep until emulation is resumed
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(30));
paused = EmulationSettings::IsPaused();
}
if(_debugger != nullptr) {
if(_debugger && _debugger->CheckFlag(DebuggerFlags::DebuggerWindowEnabled)) {
//Prevent pausing when debugger is active
EmulationSettings::ClearFlags(EmulationFlags::Paused);
}

View File

@ -11,6 +11,7 @@ enum class DebuggerFlags
DisassembleEverythingButData = 0x20,
BreakOnBrk = 0x40,
BreakOnUnofficialOpCode = 0x80,
DebuggerWindowEnabled = 0x100,
};
enum class AddressType

View File

@ -63,6 +63,8 @@ namespace Mesen.GUI.Config
public bool ConfirmExitResetPower = false;
public bool DeveloperMode = false;
public UInt32 RewindBufferSize = 300;
public bool OverrideAviFolder = false;

View File

@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public class DebugWindowManager
{
private static List<Form> _openedWindows = new List<Form>();
public static void OpenDebugWindow(DebugWindow window)
{
Form existingWindow = GetExistingSingleInstanceWindow(window);
if(existingWindow != null) {
existingWindow.BringToFront();
existingWindow.Focus();
} else {
Form frm = null;
switch(window) {
case DebugWindow.PpuViewer: frm = new frmPpuViewer(); break;
case DebugWindow.TraceLogger: frm = new frmTraceLogger(); break;
case DebugWindow.MemoryViewer: frm = new frmMemoryViewer(); break;
case DebugWindow.Assembler: frm = new frmAssembler(); break;
case DebugWindow.Debugger: frm = new frmDebugger(); break;
}
_openedWindows.Add(frm);
frm.FormClosed += Debugger_FormClosed;
frm.Show();
}
}
public static frmDebugger GetDebugger()
{
int index = _openedWindows.FindIndex((form) => form.GetType() == typeof(frmDebugger));
if(index >= 0) {
return (frmDebugger)_openedWindows[index];
}
return null;
}
public static void CloseAll()
{
List<Form> openedWindows = new List<Form>(_openedWindows);
foreach(Form frm in openedWindows) {
frm.Close();
}
}
private static Form GetExistingSingleInstanceWindow(DebugWindow window)
{
//Only one of each of these windows can be opened at once, check if one is already opened
int index = -1;
switch(window) {
case DebugWindow.TraceLogger:
index = _openedWindows.FindIndex((form) => form.GetType() == typeof(frmTraceLogger));
break;
case DebugWindow.Assembler:
index = _openedWindows.FindIndex((form) => form.GetType() == typeof(frmAssembler));
break;
case DebugWindow.Debugger:
index = _openedWindows.FindIndex((form) => form.GetType() == typeof(frmDebugger));
break;
}
if(index >= 0) {
return _openedWindows[index];
} else {
return null;
}
}
private static void Debugger_FormClosed(object sender, FormClosedEventArgs e)
{
_openedWindows.Remove((Form)sender);
if(_openedWindows.Count == 0) {
//All windows have been closed, disable debugger
DebugWorkspaceManager.Clear();
InteropEmu.DebugRelease();
}
}
}
public enum DebugWindow
{
PpuViewer,
MemoryViewer,
TraceLogger,
Assembler,
Debugger
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mesen.GUI.Config;
namespace Mesen.GUI.Debugger
{
public class DebugWorkspaceManager
{
private static DebugWorkspace _workspace;
private static string _romName;
private static object _lock = new object();
public static void SaveWorkspace()
{
if(_workspace != null) {
lock(_lock) {
if(_workspace != null) {
_workspace.WatchValues = new List<string>(WatchManager.WatchEntries);
_workspace.Labels = new List<CodeLabel>(LabelManager.GetLabels());
_workspace.Breakpoints = new List<Breakpoint>(BreakpointManager.Breakpoints);
_workspace.Save();
}
}
}
}
public static void Clear()
{
lock(_lock) {
_workspace = null;
_romName = null;
}
}
public static void ResetWorkspace()
{
if(_workspace != null) {
lock(_lock) {
if(_workspace != null) {
_workspace.Breakpoints = new List<Breakpoint>();
_workspace.Labels = new List<CodeLabel>();
_workspace.WatchValues = new List<string>();
_workspace.Save();
Clear();
}
}
}
}
public static DebugWorkspace GetWorkspace()
{
string romName = InteropEmu.GetRomInfo().GetRomName();
if(_workspace == null || _romName != romName) {
lock(_lock) {
if(_workspace == null || _romName != romName) {
if(_workspace != null) {
SaveWorkspace();
}
_romName = InteropEmu.GetRomInfo().GetRomName();
_workspace = DebugWorkspace.GetWorkspace();
//Setup labels
if(_workspace.Labels.Count == 0) {
LabelManager.ResetLabels();
if(!ConfigManager.Config.DebugInfo.DisableDefaultLabels) {
LabelManager.SetDefaultLabels(InteropEmu.FdsGetSideCount() > 0);
}
} else {
LabelManager.ResetLabels();
LabelManager.SetLabels(_workspace.Labels, false);
}
//Load watch entries
WatchManager.WatchEntries = _workspace.WatchValues;
//Load breakpoints
BreakpointManager.Breakpoints.Clear();
BreakpointManager.Breakpoints.AddRange(_workspace.Breakpoints);
}
}
}
return _workspace;
}
}
}

View File

@ -40,12 +40,14 @@ namespace Mesen.GUI.Debugger
return _reverseLookup.ContainsKey(label) ? _reverseLookup[label] : null;
}
public static void SetLabels(IEnumerable<CodeLabel> labels)
public static void SetLabels(IEnumerable<CodeLabel> labels, bool raiseEvents = true)
{
foreach(CodeLabel label in labels) {
SetLabel(label.Address, label.AddressType, label.Label, label.Comment, false);
}
OnLabelUpdated?.Invoke(null, null);
if(raiseEvents) {
OnLabelUpdated?.Invoke(null, null);
}
}
public static List<CodeLabel> GetLabels()
@ -92,95 +94,95 @@ namespace Mesen.GUI.Debugger
public static void SetDefaultLabels(bool forFDS)
{
LabelManager.SetLabel(0x2000, AddressType.Register, "PpuControl_2000", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}VPHB SINN{Environment.NewLine}|||| ||||{Environment.NewLine}|||| ||++- Base nametable address{Environment.NewLine}|||| || (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00){Environment.NewLine}|||| |+--- VRAM address increment per CPU read/write of PPUDATA{Environment.NewLine}|||| | (0: add 1, going across; 1: add 32, going down){Environment.NewLine}|||| +---- Sprite pattern table address for 8x8 sprites{Environment.NewLine}|||| (0: $0000; 1: $1000; ignored in 8x16 mode){Environment.NewLine}|||+------ Background pattern table address (0: $0000; 1: $1000){Environment.NewLine}||+------- Sprite size (0: 8x8; 1: 8x16){Environment.NewLine}|+-------- PPU master/slave select{Environment.NewLine}| (0: read backdrop from EXT pins; 1: output color on EXT pins){Environment.NewLine}+--------- Generate an NMI at the start of the{Environment.NewLine} vertical blanking interval (0: off; 1: on)");
LabelManager.SetLabel(0x2001, AddressType.Register, "PpuMask_2001", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}BGRs bMmG{Environment.NewLine}|||| ||||{Environment.NewLine}|||| |||+- Display type: (0: color, 1: grayscale){Environment.NewLine}|||| ||+-- 1: Show background in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| |+--- 1: Show sprites in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| +---- 1: Show background{Environment.NewLine}|||+------ 1: Show sprites{Environment.NewLine}||+------- Emphasize red{Environment.NewLine}|+-------- Emphasize green{Environment.NewLine}+--------- Emphasize blue");
LabelManager.SetLabel(0x2002, AddressType.Register, "PpuStatus_2002", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}VSO. ....{Environment.NewLine}|||| ||||{Environment.NewLine}|||+-++++- Least significant bits previously written into a PPU register{Environment.NewLine}||| (due to register not being updated for this address){Environment.NewLine}||+------- Sprite overflow. The intent was for this flag to be set{Environment.NewLine}|| whenever more than eight sprites appear on a scanline, but a{Environment.NewLine}|| hardware bug causes the actual behavior to be more complicated{Environment.NewLine}|| and generate false positives as well as false negatives; see{Environment.NewLine}|| PPU sprite evaluation. This flag is set during sprite{Environment.NewLine}|| evaluation and cleared at dot 1 (the second dot) of the{Environment.NewLine}|| pre-render line.{Environment.NewLine}|+-------- Sprite 0 Hit. Set when a nonzero pixel of sprite 0 overlaps{Environment.NewLine}| a nonzero background pixel; cleared at dot 1 of the pre-render{Environment.NewLine}| line. Used for raster timing.{Environment.NewLine}+--------- Vertical blank has started (0: not in vblank; 1: in vblank).{Environment.NewLine} Set at dot 1 of line 241 (the line *after* the post-render{Environment.NewLine} line); cleared after reading $2002 and at dot 1 of the{Environment.NewLine} pre-render line.");
LabelManager.SetLabel(0x2003, AddressType.Register, "OamAddr_2003", "Set OAM address - Write only");
LabelManager.SetLabel(0x2004, AddressType.Register, "OamData_2004", "Read/Write OAM data");
LabelManager.SetLabel(0x2005, AddressType.Register, "PpuScroll_2005", "Set PPU scroll, write twice - Write only");
LabelManager.SetLabel(0x2006, AddressType.Register, "PpuAddr_2006", "Set PPU address, write twice - Write only");
LabelManager.SetLabel(0x2007, AddressType.Register, "PpuData_2007", "Read/Write VRAM");
LabelManager.SetLabel(0x2000, AddressType.Register, "PpuControl_2000", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}VPHB SINN{Environment.NewLine}|||| ||||{Environment.NewLine}|||| ||++- Base nametable address{Environment.NewLine}|||| || (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00){Environment.NewLine}|||| |+--- VRAM address increment per CPU read/write of PPUDATA{Environment.NewLine}|||| | (0: add 1, going across; 1: add 32, going down){Environment.NewLine}|||| +---- Sprite pattern table address for 8x8 sprites{Environment.NewLine}|||| (0: $0000; 1: $1000; ignored in 8x16 mode){Environment.NewLine}|||+------ Background pattern table address (0: $0000; 1: $1000){Environment.NewLine}||+------- Sprite size (0: 8x8; 1: 8x16){Environment.NewLine}|+-------- PPU master/slave select{Environment.NewLine}| (0: read backdrop from EXT pins; 1: output color on EXT pins){Environment.NewLine}+--------- Generate an NMI at the start of the{Environment.NewLine} vertical blanking interval (0: off; 1: on)", false);
LabelManager.SetLabel(0x2001, AddressType.Register, "PpuMask_2001", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}BGRs bMmG{Environment.NewLine}|||| ||||{Environment.NewLine}|||| |||+- Display type: (0: color, 1: grayscale){Environment.NewLine}|||| ||+-- 1: Show background in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| |+--- 1: Show sprites in leftmost 8 pixels of screen, 0: Hide{Environment.NewLine}|||| +---- 1: Show background{Environment.NewLine}|||+------ 1: Show sprites{Environment.NewLine}||+------- Emphasize red{Environment.NewLine}|+-------- Emphasize green{Environment.NewLine}+--------- Emphasize blue", false);
LabelManager.SetLabel(0x2002, AddressType.Register, "PpuStatus_2002", $"7 bit 0{Environment.NewLine}---- ----{Environment.NewLine}VSO. ....{Environment.NewLine}|||| ||||{Environment.NewLine}|||+-++++- Least significant bits previously written into a PPU register{Environment.NewLine}||| (due to register not being updated for this address){Environment.NewLine}||+------- Sprite overflow. The intent was for this flag to be set{Environment.NewLine}|| whenever more than eight sprites appear on a scanline, but a{Environment.NewLine}|| hardware bug causes the actual behavior to be more complicated{Environment.NewLine}|| and generate false positives as well as false negatives; see{Environment.NewLine}|| PPU sprite evaluation. This flag is set during sprite{Environment.NewLine}|| evaluation and cleared at dot 1 (the second dot) of the{Environment.NewLine}|| pre-render line.{Environment.NewLine}|+-------- Sprite 0 Hit. Set when a nonzero pixel of sprite 0 overlaps{Environment.NewLine}| a nonzero background pixel; cleared at dot 1 of the pre-render{Environment.NewLine}| line. Used for raster timing.{Environment.NewLine}+--------- Vertical blank has started (0: not in vblank; 1: in vblank).{Environment.NewLine} Set at dot 1 of line 241 (the line *after* the post-render{Environment.NewLine} line, false); cleared after reading $2002 and at dot 1 of the{Environment.NewLine} pre-render line.", false);
LabelManager.SetLabel(0x2003, AddressType.Register, "OamAddr_2003", "Set OAM address - Write only", false);
LabelManager.SetLabel(0x2004, AddressType.Register, "OamData_2004", "Read/Write OAM data", false);
LabelManager.SetLabel(0x2005, AddressType.Register, "PpuScroll_2005", "Set PPU scroll, write twice - Write only", false);
LabelManager.SetLabel(0x2006, AddressType.Register, "PpuAddr_2006", "Set PPU address, write twice - Write only", false);
LabelManager.SetLabel(0x2007, AddressType.Register, "PpuData_2007", "Read/Write VRAM", false);
LabelManager.SetLabel(0x4000, AddressType.Register, "Sq1Duty_4000", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)");
LabelManager.SetLabel(0x4001, AddressType.Register, "Sq1Sweep_4001", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)");
LabelManager.SetLabel(0x4002, AddressType.Register, "Sq1Timer_4002", $"TTTT TTTT{Environment.NewLine}Timer low (T)");
LabelManager.SetLabel(0x4003, AddressType.Register, "Sq1Length_4003", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)");
LabelManager.SetLabel(0x4000, AddressType.Register, "Sq1Duty_4000", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
LabelManager.SetLabel(0x4001, AddressType.Register, "Sq1Sweep_4001", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)", false);
LabelManager.SetLabel(0x4002, AddressType.Register, "Sq1Timer_4002", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
LabelManager.SetLabel(0x4003, AddressType.Register, "Sq1Length_4003", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);
LabelManager.SetLabel(0x4004, AddressType.Register, "Sq1Duty_4004", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)");
LabelManager.SetLabel(0x4005, AddressType.Register, "Sq1Sweep_4005", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)");
LabelManager.SetLabel(0x4006, AddressType.Register, "Sq1Timer_4006", $"TTTT TTTT{Environment.NewLine}Timer low (T)");
LabelManager.SetLabel(0x4007, AddressType.Register, "Sq1Length_4007", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)");
LabelManager.SetLabel(0x4004, AddressType.Register, "Sq1Duty_4004", $"DDLC VVVV{Environment.NewLine}Duty (D), envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
LabelManager.SetLabel(0x4005, AddressType.Register, "Sq1Sweep_4005", $"EPPP NSSS{Environment.NewLine}Sweep unit: enabled (E), period (P), negate (N), shift (S)", false);
LabelManager.SetLabel(0x4006, AddressType.Register, "Sq1Timer_4006", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
LabelManager.SetLabel(0x4007, AddressType.Register, "Sq1Length_4007", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);
LabelManager.SetLabel(0x4008, AddressType.Register, "TrgLinear_4008", $"CRRR RRRR{Environment.NewLine}Length counter halt / linear counter control (C), linear counter load (R)");
LabelManager.SetLabel(0x400A, AddressType.Register, "TrgTimer_400A", $"TTTT TTTT{Environment.NewLine}Timer low (T)");
LabelManager.SetLabel(0x400B, AddressType.Register, "TrgLength_400B", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)");
LabelManager.SetLabel(0x4008, AddressType.Register, "TrgLinear_4008", $"CRRR RRRR{Environment.NewLine}Length counter halt / linear counter control (C), linear counter load (R)", false);
LabelManager.SetLabel(0x400A, AddressType.Register, "TrgTimer_400A", $"TTTT TTTT{Environment.NewLine}Timer low (T)", false);
LabelManager.SetLabel(0x400B, AddressType.Register, "TrgLength_400B", $"LLLL LTTT{Environment.NewLine}Length counter load (L), timer high (T)", false);
LabelManager.SetLabel(0x400C, AddressType.Register, "NoiseVolume_400C", $"--LC VVVV{Environment.NewLine}Envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)");
LabelManager.SetLabel(0x400E, AddressType.Register, "NoisePeriod_400E", $"L--- PPPP{Environment.NewLine}Loop noise (L), noise period (P)");
LabelManager.SetLabel(0x400F, AddressType.Register, "NoiseLength_400F", $"LLLL L---{Environment.NewLine}Length counter load (L)");
LabelManager.SetLabel(0x400C, AddressType.Register, "NoiseVolume_400C", $"--LC VVVV{Environment.NewLine}Envelope loop / length counter halt (L), constant volume (C), volume/envelope (V)", false);
LabelManager.SetLabel(0x400E, AddressType.Register, "NoisePeriod_400E", $"L--- PPPP{Environment.NewLine}Loop noise (L), noise period (P)", false);
LabelManager.SetLabel(0x400F, AddressType.Register, "NoiseLength_400F", $"LLLL L---{Environment.NewLine}Length counter load (L)", false);
LabelManager.SetLabel(0x4010, AddressType.Register, "DmcFreq_4010", $"IL-- RRRR{Environment.NewLine}IRQ enable (I), loop (L), frequency (R)");
LabelManager.SetLabel(0x4011, AddressType.Register, "DmcCounter_4011", $"-DDD DDDD{Environment.NewLine}Load counter (D)");
LabelManager.SetLabel(0x4012, AddressType.Register, "DmcAddress_4012", $"AAAA AAAA{Environment.NewLine}Sample address (A)");
LabelManager.SetLabel(0x4013, AddressType.Register, "DmcLength_4013", $"LLLL LLLL{Environment.NewLine}Sample length (L)");
LabelManager.SetLabel(0x4010, AddressType.Register, "DmcFreq_4010", $"IL-- RRRR{Environment.NewLine}IRQ enable (I), loop (L), frequency (R)", false);
LabelManager.SetLabel(0x4011, AddressType.Register, "DmcCounter_4011", $"-DDD DDDD{Environment.NewLine}Load counter (D)", false);
LabelManager.SetLabel(0x4012, AddressType.Register, "DmcAddress_4012", $"AAAA AAAA{Environment.NewLine}Sample address (A)", false);
LabelManager.SetLabel(0x4013, AddressType.Register, "DmcLength_4013", $"LLLL LLLL{Environment.NewLine}Sample length (L)", false);
LabelManager.SetLabel(0x4014, AddressType.Register, "SpriteDma_4014", "Writing $XX will upload 256 bytes of data from CPU page $XX00-$XXFF to the internal PPU OAM.");
LabelManager.SetLabel(0x4014, AddressType.Register, "SpriteDma_4014", "Writing $XX will upload 256 bytes of data from CPU page $XX00-$XXFF to the internal PPU OAM.", false);
LabelManager.SetLabel(0x4015, AddressType.Register, "ApuStatus_4015", $"Read:{Environment.NewLine}IF-D NT21{Environment.NewLine}DMC interrupt (I), frame interrupt (F), DMC active (D), length counter > 0 (N/T/2/1){Environment.NewLine+Environment.NewLine}Write:{Environment.NewLine}---D NT21{Environment.NewLine}Enable DMC (D), noise (N), triangle (T), and pulse channels (2/1)");
LabelManager.SetLabel(0x4015, AddressType.Register, "ApuStatus_4015", $"Read:{Environment.NewLine}IF-D NT21{Environment.NewLine}DMC interrupt (I), frame interrupt (F), DMC active (D), length counter > 0 (N/T/2/1){Environment.NewLine+Environment.NewLine}Write:{Environment.NewLine}---D NT21{Environment.NewLine}Enable DMC (D), noise (N), triangle (T), and pulse channels (2/1)", false);
LabelManager.SetLabel(0x4016, AddressType.Register, "Ctrl1_4016", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #1.{Environment.NewLine}{Environment.NewLine}Write:{Environment.NewLine}---- ---A{Environment.NewLine}Output data (strobe) to both controllers.");
LabelManager.SetLabel(0x4017, AddressType.Register, "Ctrl2_FrameCtr_4017", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #2.{Environment.NewLine}{Environment.NewLine}Write (Frame counter): MI-- ----{Environment.NewLine}Mode (M, 0 = 4-step, 1 = 5-step), IRQ inhibit flag (I)");
LabelManager.SetLabel(0x4016, AddressType.Register, "Ctrl1_4016", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #1.{Environment.NewLine}{Environment.NewLine}Write:{Environment.NewLine}---- ---A{Environment.NewLine}Output data (strobe) to both controllers.", false);
LabelManager.SetLabel(0x4017, AddressType.Register, "Ctrl2_FrameCtr_4017", $"Read (NES - input):{Environment.NewLine}---4 3210{Environment.NewLine}Read data from controller port #2.{Environment.NewLine}{Environment.NewLine}Write (Frame counter): MI-- ----{Environment.NewLine}Mode (M, 0 = 4-step, 1 = 5-step), IRQ inhibit flag (I)", false);
if(forFDS) {
LabelManager.SetLabel(0x01F8, AddressType.PrgRom, "LoadFiles", "Input: Pointer to Disk ID, Pointer to File List" + Environment.NewLine + "Output: A = error #, Y = # of files loaded" + Environment.NewLine + "Desc: Loads files specified by DiskID into memory from disk. Load addresses are decided by the file's header.");
LabelManager.SetLabel(0x0237, AddressType.PrgRom, "AppendFile", "Input: Pointer to Disk ID, Pointer to File Header" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Appends the file data given by DiskID to the disk. This means that the file is tacked onto the end of the disk, and the disk file count is incremented. The file is then read back to verify the write. If an error occurs during verification, the disk's file count is decremented (logically hiding the written file).");
LabelManager.SetLabel(0x0239, AddressType.PrgRom, "WriteFile", "Input: Pointer to Disk ID, Pointer to File Header, A = file #" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Same as \"Append File\", but instead of writing the file to the end of the disk, A specifies the sequential position on the disk to write the file (0 is the first). This also has the effect of setting the disk's file count to the A value, therefore logically hiding any other files that may reside after the written one.");
LabelManager.SetLabel(0x02B7, AddressType.PrgRom, "CheckFileCount", "Input: Pointer to Disk ID, A = # to set file count to" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, compares it to A, then sets the disk's file count to A.");
LabelManager.SetLabel(0x02BB, AddressType.PrgRom, "AdjustFileCount", "Input: Pointer to Disk ID, A = number to reduce current file count by" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, decrements it by A, then writes the new value back.");
LabelManager.SetLabel(0x0301, AddressType.PrgRom, "SetFileCount1", "Input: Pointer to Disk ID, A = file count minus one = # of the last file" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A + 1");
LabelManager.SetLabel(0x0305, AddressType.PrgRom, "SetFileCount", "Input: Pointer to Disk ID, A = file count" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A");
LabelManager.SetLabel(0x032A, AddressType.PrgRom, "GetDiskInfo", "Input: Pointer to Disk Info" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Fills DiskInfo up with data read off the current disk.");
LabelManager.SetLabel(0x01F8, AddressType.PrgRom, "LoadFiles", "Input: Pointer to Disk ID, Pointer to File List" + Environment.NewLine + "Output: A = error #, Y = # of files loaded" + Environment.NewLine + "Desc: Loads files specified by DiskID into memory from disk. Load addresses are decided by the file's header.", false);
LabelManager.SetLabel(0x0237, AddressType.PrgRom, "AppendFile", "Input: Pointer to Disk ID, Pointer to File Header" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Appends the file data given by DiskID to the disk. This means that the file is tacked onto the end of the disk, and the disk file count is incremented. The file is then read back to verify the write. If an error occurs during verification, the disk's file count is decremented (logically hiding the written file).", false);
LabelManager.SetLabel(0x0239, AddressType.PrgRom, "WriteFile", "Input: Pointer to Disk ID, Pointer to File Header, A = file #" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Same as \"Append File\", but instead of writing the file to the end of the disk, A specifies the sequential position on the disk to write the file (0 is the first). This also has the effect of setting the disk's file count to the A value, therefore logically hiding any other files that may reside after the written one.", false);
LabelManager.SetLabel(0x02B7, AddressType.PrgRom, "CheckFileCount", "Input: Pointer to Disk ID, A = # to set file count to" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, compares it to A, then sets the disk's file count to A.", false);
LabelManager.SetLabel(0x02BB, AddressType.PrgRom, "AdjustFileCount", "Input: Pointer to Disk ID, A = number to reduce current file count by" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Reads in disk's file count, decrements it by A, then writes the new value back.", false);
LabelManager.SetLabel(0x0301, AddressType.PrgRom, "SetFileCount1", "Input: Pointer to Disk ID, A = file count minus one = # of the last file" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A + 1", false);
LabelManager.SetLabel(0x0305, AddressType.PrgRom, "SetFileCount", "Input: Pointer to Disk ID, A = file count" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Set the file count to A", false);
LabelManager.SetLabel(0x032A, AddressType.PrgRom, "GetDiskInfo", "Input: Pointer to Disk Info" + Environment.NewLine + "Output: A = error #" + Environment.NewLine + "Desc: Fills DiskInfo up with data read off the current disk.", false);
LabelManager.SetLabel(0x0445, AddressType.PrgRom, "CheckDiskHeader", "Input: Pointer to 10 byte string at $00 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Compares the first 10 bytes on the disk coming after the FDS string, to 10 bytes pointed to by Ptr($00). To bypass the checking of any byte, a -1 can be placed in the equivelant place in the compare string. Otherwise, if the comparison fails, an appropriate error will be generated.");
LabelManager.SetLabel(0x0484, AddressType.PrgRom, "GetNumFiles", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Reads number of files stored on disk, stores the result in $06");
LabelManager.SetLabel(0x0492, AddressType.PrgRom, "SetNumFiles", "Input: " + Environment.NewLine + "Output: A = number of files " + Environment.NewLine + "Desc: Writes new number of files to disk header.");
LabelManager.SetLabel(0x04A0, AddressType.PrgRom, "FileMatchTest", "Input: Pointer to FileID list at $02 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Uses a byte string pointed at by Ptr($02) to tell the disk system which files to load. The file ID's number is searched for in the string. If an exact match is found, [$09] is 0'd, and [$0E] is incremented. If no matches are found after 20 bytes, or a -1 entry is encountered, [$09] is set to -1. If the first byte in the string is -1, the BootID number is used for matching files (any FileID that is not greater than the BootID qualifies as a match).");
LabelManager.SetLabel(0x04DA, AddressType.PrgRom, "SkipFiles", "Input: Number of files to skip in $06 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Skips over specified number of files.");
LabelManager.SetLabel(0x0445, AddressType.PrgRom, "CheckDiskHeader", "Input: Pointer to 10 byte string at $00 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Compares the first 10 bytes on the disk coming after the FDS string, to 10 bytes pointed to by Ptr($00). To bypass the checking of any byte, a -1 can be placed in the equivelant place in the compare string. Otherwise, if the comparison fails, an appropriate error will be generated.", false);
LabelManager.SetLabel(0x0484, AddressType.PrgRom, "GetNumFiles", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Reads number of files stored on disk, stores the result in $06", false);
LabelManager.SetLabel(0x0492, AddressType.PrgRom, "SetNumFiles", "Input: " + Environment.NewLine + "Output: A = number of files " + Environment.NewLine + "Desc: Writes new number of files to disk header.", false);
LabelManager.SetLabel(0x04A0, AddressType.PrgRom, "FileMatchTest", "Input: Pointer to FileID list at $02 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Uses a byte string pointed at by Ptr($02) to tell the disk system which files to load. The file ID's number is searched for in the string. If an exact match is found, [$09] is 0'd, and [$0E] is incremented. If no matches are found after 20 bytes, or a -1 entry is encountered, [$09] is set to -1. If the first byte in the string is -1, the BootID number is used for matching files (any FileID that is not greater than the BootID qualifies as a match).", false);
LabelManager.SetLabel(0x04DA, AddressType.PrgRom, "SkipFiles", "Input: Number of files to skip in $06 " + Environment.NewLine + "Output: " + Environment.NewLine + "Desc: Skips over specified number of files.", false);
LabelManager.SetLabel(0x0149, AddressType.PrgRom, "Delay132", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: 132 clock cycle delay");
LabelManager.SetLabel(0x0153, AddressType.PrgRom, "Delayms", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: X, Y " + Environment.NewLine + "Desc: Delay routine, Y = delay in ms (approximate)");
LabelManager.SetLabel(0x0161, AddressType.PrgRom, "DisPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites and background");
LabelManager.SetLabel(0x016B, AddressType.PrgRom, "EnPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites and background");
LabelManager.SetLabel(0x0171, AddressType.PrgRom, "DisObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites");
LabelManager.SetLabel(0x0178, AddressType.PrgRom, "EnObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites");
LabelManager.SetLabel(0x017E, AddressType.PrgRom, "DisPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable background");
LabelManager.SetLabel(0x0185, AddressType.PrgRom, "EnPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable background");
LabelManager.SetLabel(0x01B2, AddressType.PrgRom, "VINTWait", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: $ff " + Environment.NewLine + "Desc: Wait until next VBlank NMI fires, and return (for programs that does it the \"everything in main\" way). NMI vector selection at $100 is preserved, but further VBlanks are disabled.");
LabelManager.SetLabel(0x07BB, AddressType.PrgRom, "VRAMStructWrite", "Input: Pointer to VRAM buffer to be written " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $ff " + Environment.NewLine + "Desc: Set VRAM increment to 1 (clear [[PPUCTRL]]/$ff bit 2), and write a VRAM buffer to VRAM. Read below for information on the structure.");
LabelManager.SetLabel(0x0844, AddressType.PrgRom, "FetchDirectPtr", "Input: " + Environment.NewLine + "Output: $00, $01 = pointer fetched " + Environment.NewLine + "Affects: A, X, Y, $05, $06 " + Environment.NewLine + "Desc: Fetch a direct pointer from the stack (the pointer should be placed after the return address of the routine that calls this one (see \"important notes\" above)), save the pointer at ($00) and fix the return address.");
LabelManager.SetLabel(0x086A, AddressType.PrgRom, "WriteVRAMBuffer", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $301, $302 " + Environment.NewLine + "Desc: Write the VRAM Buffer at $302 to VRAM. Read below for information on the structure.");
LabelManager.SetLabel(0x08B3, AddressType.PrgRom, "ReadVRAMBuffer", "Input: X = start address of read buffer, Y = # of bytes to read " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: Read individual bytes from VRAM to the VRAMBuffer. (see notes below)");
LabelManager.SetLabel(0x08D2, AddressType.PrgRom, "PrepareVRAMString", "Input: A = High VRAM address, X = Low VRAM address, Y = string length, Direct Pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : string didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies pointed data into the VRAM buffer.");
LabelManager.SetLabel(0x08E1, AddressType.PrgRom, "PrepareVRAMStrings", "Input: A = High VRAM address, X = Low VRAM address, Direct pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : data didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies a 2D string into the VRAM buffer. The first byte of the data determines the width and height of the following string (in tiles): Upper nybble = height, lower nybble = width.");
LabelManager.SetLabel(0x094F, AddressType.PrgRom, "GetVRAMBufferByte", "Input: X = starting index of read buffer, Y = # of address to compare (starting at 1), $00, $01 = address to read from " + Environment.NewLine + "Output: carry clear : a previously read byte was returned, carry set : no byte was read, should wait next call to ReadVRAMBuffer " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: This routine was likely planned to be used in order to avoid useless latency on a VRAM reads (see notes below). It compares the VRAM address in ($00) with the Yth (starting at 1) address of the read buffer. If both addresses match, the corresponding data byte is returned exit with c clear. If the addresses are different, the buffer address is overwritten by the address in ($00) and the routine exit with c set.");
LabelManager.SetLabel(0x097D, AddressType.PrgRom, "Pixel2NamConv", "Input: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Output: $00 = High nametable address, $01 = Low nametable address " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert pixel screen coordinates to corresponding nametable address (assumes no scrolling, and points to first nametable at $2000-$23ff).");
LabelManager.SetLabel(0x0997, AddressType.PrgRom, "Nam2PixelConv", "Input: $00 = High nametable address, $01 = low nametable address " + Environment.NewLine + "Output: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert a nametable address to corresponding pixel coordinates (assume no scrolling).");
LabelManager.SetLabel(0x09B1, AddressType.PrgRom, "Random", "Input: X = Zero Page address where the random bytes are placed, Y = # of shift register bytes (normally $02) " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00 " + Environment.NewLine + "Desc: This is a shift-register based random number generator, normally takes 2 bytes (using more won't affect random sequence). On reset you are supposed to write some non-zero values here (BIOS uses writes $d0, $d0), and call this routine several times before the data is actually random. Each call of this routine will shift the bytes ''right''.");
LabelManager.SetLabel(0x09C8, AddressType.PrgRom, "SpriteDMA", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine does sprite DMA from RAM $200-$2ff");
LabelManager.SetLabel(0x09D3, AddressType.PrgRom, "CounterLogic", "Input: A, Y = end Zeropage address of counters, X = start zeropage address of counters " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00 " + Environment.NewLine + "Desc: This decrements several counters in Zeropage. The first counter is a decimal counter 9 -> 8 -> 7 -> ... -> 1 -> 0 -> 9 -> ... Counters 1...A are simply decremented and stays at 0. Counters A+1...Y are decremented when the first counter does a 0 -> 9 transition, and stays at 0.");
LabelManager.SetLabel(0x09EB, AddressType.PrgRom, "ReadPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 data, $f6 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01, " + Environment.NewLine + "Desc: This read hardwired famicom joypads.");
LabelManager.SetLabel(0x0A1A, AddressType.PrgRom, "ReadDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired famicom joypads, and detect up->down button transitions");
LabelManager.SetLabel(0x0A1F, AddressType.PrgRom, "ReadOrDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions.");
LabelManager.SetLabel(0x0A36, AddressType.PrgRom, "ReadDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired Famicom joypads, and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.");
LabelManager.SetLabel(0x0A4C, AddressType.PrgRom, "ReadOrDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.");
LabelManager.SetLabel(0x0A68, AddressType.PrgRom, "ReadDownExpPads", "Input: $f1-$f4 = up->down transitions, $f5-$f8 = Joypad data in the order : Pad1, Pad2, Expansion1, Expansion2 " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypad, but stores their data separately instead of ORing them together like the other routines does. This routine is NOT DMC fortified.");
LabelManager.SetLabel(0x0A84, AddressType.PrgRom, "VRAMFill", "Input: A = High VRAM Address (aka tile row #), X = Fill value, Y = # of tile rows OR attribute fill data " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02 " + Environment.NewLine + "Desc: This routine does 2 things : If A < $20, it fills pattern table data with the value in X for 16 * Y tiles. If A >= $20, it fills the corresponding nametable with the value in X and attribute table with the value in Y.");
LabelManager.SetLabel(0x0Ad2, AddressType.PrgRom, "MemFill", "Input: A = fill value, X = first page #, Y = last page # " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: This routines fills RAM pages with specified value.");
LabelManager.SetLabel(0x0AEA, AddressType.PrgRom, "SetScroll", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine set scroll registers according to values in $fc, $fd and $ff. Should typically be called in VBlank after VRAM updates");
LabelManager.SetLabel(0x0AFD, AddressType.PrgRom, "JumpEngine", "Input: A = Jump table entry " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: The instruction calling this is supposed to be followed by a jump table (16-bit pointers little endian, up to 128 pointers). A is the entry # to jump to, return address on stack is used to get jump table entries.");
LabelManager.SetLabel(0x0B13, AddressType.PrgRom, "ReadKeyboard", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: Read Family Basic Keyboard expansion (detail is under analysis)");
LabelManager.SetLabel(0x0B66, AddressType.PrgRom, "LoadTileset", "Input: A = Low VRAM Address & Flags, Y = Hi VRAM Address, X = # of tiles to transfer to/from VRAM " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04 " + Environment.NewLine + "Desc: This routine can read and write 2BP and 1BP tilesets to/from VRAM. See appendix below about the flags.");
LabelManager.SetLabel(0x0C22, AddressType.PrgRom, "unk_EC22", "Some kind of logic that some games use. (detail is under analysis)");
LabelManager.SetLabel(0x0149, AddressType.PrgRom, "Delay132", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: 132 clock cycle delay", false);
LabelManager.SetLabel(0x0153, AddressType.PrgRom, "Delayms", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: X, Y " + Environment.NewLine + "Desc: Delay routine, Y = delay in ms (approximate)", false);
LabelManager.SetLabel(0x0161, AddressType.PrgRom, "DisPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites and background", false);
LabelManager.SetLabel(0x016B, AddressType.PrgRom, "EnPFObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites and background", false);
LabelManager.SetLabel(0x0171, AddressType.PrgRom, "DisObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable sprites", false);
LabelManager.SetLabel(0x0178, AddressType.PrgRom, "EnObj", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable sprites", false);
LabelManager.SetLabel(0x017E, AddressType.PrgRom, "DisPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Disable background", false);
LabelManager.SetLabel(0x0185, AddressType.PrgRom, "EnPF", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, $fe " + Environment.NewLine + "Desc: Enable background", false);
LabelManager.SetLabel(0x01B2, AddressType.PrgRom, "VINTWait", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: $ff " + Environment.NewLine + "Desc: Wait until next VBlank NMI fires, and return (for programs that does it the \"everything in main\" way). NMI vector selection at $100 is preserved, but further VBlanks are disabled.", false);
LabelManager.SetLabel(0x07BB, AddressType.PrgRom, "VRAMStructWrite", "Input: Pointer to VRAM buffer to be written " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $ff " + Environment.NewLine + "Desc: Set VRAM increment to 1 (clear [[PPUCTRL]]/$ff bit 2), and write a VRAM buffer to VRAM. Read below for information on the structure.", false);
LabelManager.SetLabel(0x0844, AddressType.PrgRom, "FetchDirectPtr", "Input: " + Environment.NewLine + "Output: $00, $01 = pointer fetched " + Environment.NewLine + "Affects: A, X, Y, $05, $06 " + Environment.NewLine + "Desc: Fetch a direct pointer from the stack (the pointer should be placed after the return address of the routine that calls this one (see \"important notes\" above)), save the pointer at ($00) and fix the return address.", false);
LabelManager.SetLabel(0x086A, AddressType.PrgRom, "WriteVRAMBuffer", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $301, $302 " + Environment.NewLine + "Desc: Write the VRAM Buffer at $302 to VRAM. Read below for information on the structure.", false);
LabelManager.SetLabel(0x08B3, AddressType.PrgRom, "ReadVRAMBuffer", "Input: X = start address of read buffer, Y = # of bytes to read " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: Read individual bytes from VRAM to the VRAMBuffer. (see notes below)", false);
LabelManager.SetLabel(0x08D2, AddressType.PrgRom, "PrepareVRAMString", "Input: A = High VRAM address, X = Low VRAM address, Y = string length, Direct Pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : string didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies pointed data into the VRAM buffer.", false);
LabelManager.SetLabel(0x08E1, AddressType.PrgRom, "PrepareVRAMStrings", "Input: A = High VRAM address, X = Low VRAM address, Direct pointer = data to be written to VRAM " + Environment.NewLine + "Output: A = $ff : no error, A = $01 : data didn't fit in buffer " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04, $05, $06 " + Environment.NewLine + "Desc: This routine copies a 2D string into the VRAM buffer. The first byte of the data determines the width and height of the following string (in tiles): Upper nybble = height, lower nybble = width.", false);
LabelManager.SetLabel(0x094F, AddressType.PrgRom, "GetVRAMBufferByte", "Input: X = starting index of read buffer, Y = # of address to compare (starting at 1), $00, $01 = address to read from " + Environment.NewLine + "Output: carry clear : a previously read byte was returned, carry set : no byte was read, should wait next call to ReadVRAMBuffer " + Environment.NewLine + "Affects: A, X, Y " + Environment.NewLine + "Desc: This routine was likely planned to be used in order to avoid useless latency on a VRAM reads (see notes below). It compares the VRAM address in ($00) with the Yth (starting at 1) address of the read buffer. If both addresses match, the corresponding data byte is returned exit with c clear. If the addresses are different, the buffer address is overwritten by the address in ($00) and the routine exit with c set.", false);
LabelManager.SetLabel(0x097D, AddressType.PrgRom, "Pixel2NamConv", "Input: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Output: $00 = High nametable address, $01 = Low nametable address " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert pixel screen coordinates to corresponding nametable address (assumes no scrolling, and points to first nametable at $2000-$23ff).", false);
LabelManager.SetLabel(0x0997, AddressType.PrgRom, "Nam2PixelConv", "Input: $00 = High nametable address, $01 = low nametable address " + Environment.NewLine + "Output: $02 = Pixel X cord, $03 = Pixel Y cord " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine convert a nametable address to corresponding pixel coordinates (assume no scrolling).", false);
LabelManager.SetLabel(0x09B1, AddressType.PrgRom, "Random", "Input: X = Zero Page address where the random bytes are placed, Y = # of shift register bytes (normally $02) " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00 " + Environment.NewLine + "Desc: This is a shift-register based random number generator, normally takes 2 bytes (using more won't affect random sequence). On reset you are supposed to write some non-zero values here (BIOS uses writes $d0, $d0), and call this routine several times before the data is actually random. Each call of this routine will shift the bytes ''right''.", false);
LabelManager.SetLabel(0x09C8, AddressType.PrgRom, "SpriteDMA", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine does sprite DMA from RAM $200-$2ff", false);
LabelManager.SetLabel(0x09D3, AddressType.PrgRom, "CounterLogic", "Input: A, Y = end Zeropage address of counters, X = start zeropage address of counters " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00 " + Environment.NewLine + "Desc: This decrements several counters in Zeropage. The first counter is a decimal counter 9 -> 8 -> 7 -> ... -> 1 -> 0 -> 9 -> ... Counters 1...A are simply decremented and stays at 0. Counters A+1...Y are decremented when the first counter does a 0 -> 9 transition, and stays at 0.", false);
LabelManager.SetLabel(0x09EB, AddressType.PrgRom, "ReadPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 data, $f6 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01, " + Environment.NewLine + "Desc: This read hardwired famicom joypads.", false);
LabelManager.SetLabel(0x0A1A, AddressType.PrgRom, "ReadDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired famicom joypads, and detect up->down button transitions", false);
LabelManager.SetLabel(0x0A1F, AddressType.PrgRom, "ReadOrDownPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions.", false);
LabelManager.SetLabel(0x0A36, AddressType.PrgRom, "ReadDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This reads hardwired Famicom joypads, and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.", false);
LabelManager.SetLabel(0x0A4C, AddressType.PrgRom, "ReadOrDownVerifyPads", "Input: " + Environment.NewLine + "Output: $f5 = Joypad #1 up->down transitions, $f6 = Joypad #2 up->down transitions $f7 = Joypad #1 data, $f8 = Joypad #2 data " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypads and detect up->down button transitions. Data is read until two consecutive read matches to work around the DMC reading glitches.", false);
LabelManager.SetLabel(0x0A68, AddressType.PrgRom, "ReadDownExpPads", "Input: $f1-$f4 = up->down transitions, $f5-$f8 = Joypad data in the order : Pad1, Pad2, Expansion1, Expansion2 " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, $00, $01 " + Environment.NewLine + "Desc: This read both hardwired famicom and expansion port joypad, but stores their data separately instead of ORing them together like the other routines does. This routine is NOT DMC fortified.", false);
LabelManager.SetLabel(0x0A84, AddressType.PrgRom, "VRAMFill", "Input: A = High VRAM Address (aka tile row #), X = Fill value, Y = # of tile rows OR attribute fill data " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02 " + Environment.NewLine + "Desc: This routine does 2 things : If A < $20, it fills pattern table data with the value in X for 16 * Y tiles. If A >= $20, it fills the corresponding nametable with the value in X and attribute table with the value in Y.", false);
LabelManager.SetLabel(0x0Ad2, AddressType.PrgRom, "MemFill", "Input: A = fill value, X = first page #, Y = last page # " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: This routines fills RAM pages with specified value.", false);
LabelManager.SetLabel(0x0AEA, AddressType.PrgRom, "SetScroll", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A " + Environment.NewLine + "Desc: This routine set scroll registers according to values in $fc, $fd and $ff. Should typically be called in VBlank after VRAM updates", false);
LabelManager.SetLabel(0x0AFD, AddressType.PrgRom, "JumpEngine", "Input: A = Jump table entry " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01 " + Environment.NewLine + "Desc: The instruction calling this is supposed to be followed by a jump table (16-bit pointers little endian, up to 128 pointers). A is the entry # to jump to, return address on stack is used to get jump table entries.", false);
LabelManager.SetLabel(0x0B13, AddressType.PrgRom, "ReadKeyboard", "Input: " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: " + Environment.NewLine + "Desc: Read Family Basic Keyboard expansion (detail is under analysis)", false);
LabelManager.SetLabel(0x0B66, AddressType.PrgRom, "LoadTileset", "Input: A = Low VRAM Address & Flags, Y = Hi VRAM Address, X = # of tiles to transfer to/from VRAM " + Environment.NewLine + "Output: " + Environment.NewLine + "Affects: A, X, Y, $00, $01, $02, $03, $04 " + Environment.NewLine + "Desc: This routine can read and write 2BP and 1BP tilesets to/from VRAM. See appendix below about the flags.", false);
LabelManager.SetLabel(0x0C22, AddressType.PrgRom, "unk_EC22", "Some kind of logic that some games use. (detail is under analysis)", false);
}
}
}

View File

@ -17,7 +17,7 @@ namespace Mesen.GUI.Debugger
get { return _watchEntries; }
set
{
_watchEntries = value;
_watchEntries = new List<string>(value);
WatchChanged?.Invoke(null, EventArgs.Empty);
}
}

View File

@ -180,8 +180,6 @@ namespace Mesen.GUI.Debugger
private void btnExecute_Click(object sender, EventArgs e)
{
WaitUntilBreak();
List<string> warningMessages = new List<string>();
if(_hasParsingErrors) {
warningMessages.Add("Warning: The code contains parsing errors - lines with errors will be ignored.");
@ -190,6 +188,8 @@ namespace Mesen.GUI.Debugger
warningMessages.Add("This will assemble and execute the code in the $3000-$3FFF range, starting at address $3000." + Environment.NewLine + Environment.NewLine + "Execute?");
if(MessageBox.Show(string.Join(Environment.NewLine+Environment.NewLine, warningMessages.ToArray()), "Warning", MessageBoxButtons.OKCancel) == DialogResult.OK) {
WaitUntilBreak();
UInt16 originalAddress = _startAddress;
_startAddress = 0x3000;
UpdateWindow();
@ -209,8 +209,6 @@ namespace Mesen.GUI.Debugger
private void btnOk_Click(object sender, EventArgs e)
{
WaitUntilBreak();
List<string> warningMessages = new List<string>();
if(_hasParsingErrors) {
warningMessages.Add("Warning: The code contains parsing errors - lines with errors will be ignored.");
@ -227,6 +225,8 @@ namespace Mesen.GUI.Debugger
}
if(warningMessages.Count == 0 || MessageBox.Show(string.Join(Environment.NewLine+Environment.NewLine, warningMessages.ToArray()) + Environment.NewLine + Environment.NewLine + "OK?", "Warning", MessageBoxButtons.OKCancel) == DialogResult.OK) {
WaitUntilBreak();
byte lastByte = ctrlHexBox.ByteProvider.ReadByte(ctrlHexBox.ByteProvider.Length - 1);
bool endsWithRtiRts = lastByte == 0x40 || lastByte == 0x60;
int byteGap = (int)(_blockLength - ctrlHexBox.ByteProvider.Length);
@ -241,6 +241,12 @@ namespace Mesen.GUI.Debugger
InteropEmu.DebugSetMemoryValues(DebugMemoryType.CpuMemory, (UInt32)_startAddress, bytes.ToArray());
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
debugger.UpdateDebugger(false);
} else {
InteropEmu.DebugRun();
}
this.DialogResult = DialogResult.OK;
this.Close();
}

View File

@ -53,6 +53,7 @@ namespace Mesen.GUI.Debugger
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSaveRom = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditHeader = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripSeparator();
this.mnuWorkspace = new System.Windows.Forms.ToolStripMenuItem();
this.mnuImportLabels = new System.Windows.Forms.ToolStripMenuItem();
@ -148,7 +149,6 @@ namespace Mesen.GUI.Debugger
this.lblCyclesElapsed = new System.Windows.Forms.ToolStripStatusLabel();
this.ctrlPpuMemoryMapping = new Mesen.GUI.Debugger.Controls.ctrlMemoryMapping();
this.ctrlCpuMemoryMapping = new Mesen.GUI.Debugger.Controls.ctrlMemoryMapping();
this.mnuEditHeader = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit();
this.splitContainer.Panel1.SuspendLayout();
this.splitContainer.Panel2.SuspendLayout();
@ -193,7 +193,7 @@ namespace Mesen.GUI.Debugger
this.splitContainer.Panel2.Controls.Add(this.tableLayoutPanel10);
this.splitContainer.Panel2MinSize = 100;
this.splitContainer.Size = new System.Drawing.Size(1172, 573);
this.splitContainer.SplitterDistance = 447;
this.splitContainer.SplitterDistance = 444;
this.splitContainer.SplitterWidth = 7;
this.splitContainer.TabIndex = 1;
this.splitContainer.TabStop = false;
@ -216,8 +216,8 @@ namespace Mesen.GUI.Debugger
//
this.ctrlSplitContainerTop.Panel2.Controls.Add(this.tlpFunctionLabelLists);
this.ctrlSplitContainerTop.Panel2MinSize = 150;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1172, 447);
this.ctrlSplitContainerTop.SplitterDistance = 926;
this.ctrlSplitContainerTop.Size = new System.Drawing.Size(1172, 444);
this.ctrlSplitContainerTop.SplitterDistance = 923;
this.ctrlSplitContainerTop.SplitterWidth = 7;
this.ctrlSplitContainerTop.TabIndex = 3;
this.ctrlSplitContainerTop.PanelCollapsed += new System.EventHandler(this.ctrlSplitContainerTop_PanelCollapsed);
@ -238,7 +238,7 @@ namespace Mesen.GUI.Debugger
this.tlpTop.Name = "tlpTop";
this.tlpTop.RowCount = 1;
this.tlpTop.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpTop.Size = new System.Drawing.Size(926, 447);
this.tlpTop.Size = new System.Drawing.Size(923, 444);
this.tlpTop.TabIndex = 2;
//
// ctrlDebuggerCode
@ -247,7 +247,7 @@ namespace Mesen.GUI.Debugger
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(462, 441);
this.ctrlDebuggerCode.Size = new System.Drawing.Size(459, 438);
this.ctrlDebuggerCode.TabIndex = 2;
this.ctrlDebuggerCode.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
this.ctrlDebuggerCode.OnSetNextStatement += new Mesen.GUI.Debugger.ctrlDebuggerCode.AddressEventHandler(this.ctrlDebuggerCode_OnSetNextStatement);
@ -256,10 +256,10 @@ namespace Mesen.GUI.Debugger
// ctrlConsoleStatus
//
this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlConsoleStatus.Location = new System.Drawing.Point(468, 0);
this.ctrlConsoleStatus.Location = new System.Drawing.Point(465, 0);
this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0);
this.ctrlConsoleStatus.Name = "ctrlConsoleStatus";
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 447);
this.ctrlConsoleStatus.Size = new System.Drawing.Size(458, 444);
this.ctrlConsoleStatus.TabIndex = 3;
this.ctrlConsoleStatus.OnGotoLocation += new System.EventHandler(this.ctrlConsoleStatus_OnGotoLocation);
//
@ -267,9 +267,9 @@ namespace Mesen.GUI.Debugger
//
this.ctrlDebuggerCodeSplit.Code = null;
this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(471, 3);
this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(468, 3);
this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit";
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 441);
this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 438);
this.ctrlDebuggerCodeSplit.TabIndex = 4;
this.ctrlDebuggerCodeSplit.Visible = false;
this.ctrlDebuggerCodeSplit.OnEditCode += new Mesen.GUI.Debugger.ctrlDebuggerCode.AssemblerEventHandler(this.ctrlDebuggerCode_OnEditCode);
@ -289,16 +289,16 @@ namespace Mesen.GUI.Debugger
this.tlpFunctionLabelLists.RowCount = 2;
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(239, 447);
this.tlpFunctionLabelLists.Size = new System.Drawing.Size(242, 444);
this.tlpFunctionLabelLists.TabIndex = 5;
//
// grpLabels
//
this.grpLabels.Controls.Add(this.ctrlLabelList);
this.grpLabels.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpLabels.Location = new System.Drawing.Point(3, 226);
this.grpLabels.Location = new System.Drawing.Point(3, 225);
this.grpLabels.Name = "grpLabels";
this.grpLabels.Size = new System.Drawing.Size(233, 218);
this.grpLabels.Size = new System.Drawing.Size(236, 216);
this.grpLabels.TabIndex = 6;
this.grpLabels.TabStop = false;
this.grpLabels.Text = "Labels";
@ -308,7 +308,7 @@ namespace Mesen.GUI.Debugger
this.ctrlLabelList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlLabelList.Location = new System.Drawing.Point(3, 16);
this.ctrlLabelList.Name = "ctrlLabelList";
this.ctrlLabelList.Size = new System.Drawing.Size(227, 199);
this.ctrlLabelList.Size = new System.Drawing.Size(230, 197);
this.ctrlLabelList.TabIndex = 0;
this.ctrlLabelList.OnFindOccurrence += new System.EventHandler(this.ctrlLabelList_OnFindOccurrence);
this.ctrlLabelList.OnLabelSelected += new System.EventHandler(this.ctrlLabelList_OnLabelSelected);
@ -319,7 +319,7 @@ namespace Mesen.GUI.Debugger
this.grpFunctions.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpFunctions.Location = new System.Drawing.Point(3, 3);
this.grpFunctions.Name = "grpFunctions";
this.grpFunctions.Size = new System.Drawing.Size(233, 217);
this.grpFunctions.Size = new System.Drawing.Size(236, 216);
this.grpFunctions.TabIndex = 5;
this.grpFunctions.TabStop = false;
this.grpFunctions.Text = "Functions";
@ -329,7 +329,7 @@ namespace Mesen.GUI.Debugger
this.ctrlFunctionList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlFunctionList.Location = new System.Drawing.Point(3, 16);
this.ctrlFunctionList.Name = "ctrlFunctionList";
this.ctrlFunctionList.Size = new System.Drawing.Size(227, 198);
this.ctrlFunctionList.Size = new System.Drawing.Size(230, 197);
this.ctrlFunctionList.TabIndex = 0;
this.ctrlFunctionList.OnFindOccurrence += new System.EventHandler(this.ctrlFunctionList_OnFindOccurrence);
this.ctrlFunctionList.OnFunctionSelected += new System.EventHandler(this.ctrlFunctionList_OnFunctionSelected);
@ -350,7 +350,7 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel10.Size = new System.Drawing.Size(1172, 119);
this.tableLayoutPanel10.Size = new System.Drawing.Size(1172, 122);
this.tableLayoutPanel10.TabIndex = 0;
//
// grpWatch
@ -360,7 +360,7 @@ namespace Mesen.GUI.Debugger
this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpWatch.Location = new System.Drawing.Point(3, 3);
this.grpWatch.Name = "grpWatch";
this.grpWatch.Size = new System.Drawing.Size(384, 113);
this.grpWatch.Size = new System.Drawing.Size(384, 116);
this.grpWatch.TabIndex = 2;
this.grpWatch.TabStop = false;
this.grpWatch.Text = "Watch";
@ -380,7 +380,7 @@ namespace Mesen.GUI.Debugger
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(378, 94);
this.ctrlWatch.Size = new System.Drawing.Size(378, 97);
this.ctrlWatch.TabIndex = 0;
//
// grpBreakpoints
@ -389,7 +389,7 @@ namespace Mesen.GUI.Debugger
this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpBreakpoints.Location = new System.Drawing.Point(393, 3);
this.grpBreakpoints.Name = "grpBreakpoints";
this.grpBreakpoints.Size = new System.Drawing.Size(384, 113);
this.grpBreakpoints.Size = new System.Drawing.Size(384, 116);
this.grpBreakpoints.TabIndex = 3;
this.grpBreakpoints.TabStop = false;
this.grpBreakpoints.Text = "Breakpoints";
@ -399,7 +399,7 @@ namespace Mesen.GUI.Debugger
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(378, 94);
this.ctrlBreakpoints.Size = new System.Drawing.Size(378, 97);
this.ctrlBreakpoints.TabIndex = 0;
this.ctrlBreakpoints.BreakpointNavigation += new System.EventHandler(this.ctrlBreakpoints_BreakpointNavigation);
//
@ -409,7 +409,7 @@ namespace Mesen.GUI.Debugger
this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCallstack.Location = new System.Drawing.Point(783, 3);
this.grpCallstack.Name = "grpCallstack";
this.grpCallstack.Size = new System.Drawing.Size(386, 113);
this.grpCallstack.Size = new System.Drawing.Size(386, 116);
this.grpCallstack.TabIndex = 4;
this.grpCallstack.TabStop = false;
this.grpCallstack.Text = "Call Stack";
@ -419,7 +419,7 @@ namespace Mesen.GUI.Debugger
this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlCallstack.Location = new System.Drawing.Point(3, 16);
this.ctrlCallstack.Name = "ctrlCallstack";
this.ctrlCallstack.Size = new System.Drawing.Size(380, 94);
this.ctrlCallstack.Size = new System.Drawing.Size(380, 97);
this.ctrlCallstack.TabIndex = 0;
this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected);
//
@ -459,6 +459,14 @@ namespace Mesen.GUI.Debugger
this.mnuSaveRom.Text = "Save ROM as...";
this.mnuSaveRom.Click += new System.EventHandler(this.mnuSaveRom_Click);
//
// mnuEditHeader
//
this.mnuEditHeader.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditHeader.Name = "mnuEditHeader";
this.mnuEditHeader.Size = new System.Drawing.Size(162, 22);
this.mnuEditHeader.Text = "Edit iNES Header";
this.mnuEditHeader.Click += new System.EventHandler(this.mnuEditHeader_Click);
//
// toolStripMenuItem14
//
this.toolStripMenuItem14.Name = "toolStripMenuItem14";
@ -1252,14 +1260,6 @@ namespace Mesen.GUI.Debugger
this.ctrlCpuMemoryMapping.Text = "ctrlMemoryMapping1";
this.ctrlCpuMemoryMapping.Visible = false;
//
// mnuEditHeader
//
this.mnuEditHeader.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditHeader.Name = "mnuEditHeader";
this.mnuEditHeader.Size = new System.Drawing.Size(162, 22);
this.mnuEditHeader.Text = "Edit iNES Header";
this.mnuEditHeader.Click += new System.EventHandler(this.mnuEditHeader_Click);
//
// frmDebugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View File

@ -18,15 +18,12 @@ namespace Mesen.GUI.Debugger
{
public partial class frmDebugger : BaseForm
{
private List<Form> _childForms = new List<Form>();
private bool _debuggerInitialized = false;
private bool _firstBreak = true;
private int _previousCycle = 0;
private InteropEmu.NotificationListener _notifListener;
private ctrlDebuggerCode _lastCodeWindow;
private frmTraceLogger _traceLogger;
private DebugWorkspace _workspace;
public frmDebugger()
{
@ -42,6 +39,8 @@ namespace Mesen.GUI.Debugger
mnuCode.Visible = false;
}
bool debuggerAlreadyRunning = InteropEmu.DebugIsDebuggerRunning();
ctrlConsoleStatus.OnStateChanged += ctrlConsoleStatus_OnStateChanged;
LabelManager.OnLabelUpdated += LabelManager_OnLabelUpdated;
BreakpointManager.BreakpointsChanged += BreakpointManager_BreakpointsChanged;
@ -115,9 +114,15 @@ namespace Mesen.GUI.Debugger
//Pause a few frames later to give the debugger a chance to disassemble some code
_firstBreak = true;
InteropEmu.SetFlag(EmulationFlags.ForceMaxSpeed, true);
InteropEmu.DebugStep(30000);
if(!debuggerAlreadyRunning) {
InteropEmu.SetFlag(EmulationFlags.ForceMaxSpeed, true);
InteropEmu.DebugStep(5000);
} else {
//Break once to show code and then resume execution
InteropEmu.DebugStep(1);
}
UpdateDebuggerFlags();
UpdateCdlRatios();
tmrCdlRatios.Start();
@ -152,41 +157,13 @@ namespace Mesen.GUI.Debugger
}
}
private void SaveWorkspace()
{
if(_workspace != null) {
_workspace.WatchValues = WatchManager.WatchEntries;
_workspace.Labels = LabelManager.GetLabels();
_workspace.Breakpoints = BreakpointManager.Breakpoints;
_workspace.Save();
}
}
private void UpdateWorkspace()
{
SaveWorkspace();
_workspace = DebugWorkspace.GetWorkspace();
LabelManager.OnLabelUpdated -= LabelManager_OnLabelUpdated;
if(_workspace.Labels.Count == 0) {
LabelManager.ResetLabels();
if(!ConfigManager.Config.DebugInfo.DisableDefaultLabels) {
LabelManager.SetDefaultLabels(InteropEmu.FdsGetSideCount() > 0);
}
} else {
LabelManager.ResetLabels();
LabelManager.SetLabels(_workspace.Labels);
}
LabelManager.OnLabelUpdated += LabelManager_OnLabelUpdated;
DebugWorkspaceManager.SaveWorkspace();
DebugWorkspace workspace = DebugWorkspaceManager.GetWorkspace();
ctrlLabelList.UpdateLabelList();
ctrlFunctionList.UpdateFunctionList(true);
WatchManager.WatchEntries = _workspace.WatchValues;
BreakpointManager.Breakpoints.Clear();
BreakpointManager.Breakpoints.AddRange(_workspace.Breakpoints);
ctrlBreakpoints.RefreshList();
}
@ -226,7 +203,7 @@ namespace Mesen.GUI.Debugger
if(mnuBreakOnBrk.Checked) {
flags |= DebuggerFlags.BreakOnBrk;
}
InteropEmu.DebugSetFlags(flags);
InteropEmu.DebugSetFlags(flags | DebuggerFlags.DebuggerWindowEnabled);
}
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
@ -292,7 +269,7 @@ namespace Mesen.GUI.Debugger
mnuGoToIrqHandler.Text = "IRQ Handler ($" + irqHandler.ToString("X4") + ")";
}
private void UpdateDebugger(bool updateActiveAddress = true)
public void UpdateDebugger(bool updateActiveAddress = true)
{
if(!_debuggerInitialized) {
return;
@ -368,18 +345,6 @@ namespace Mesen.GUI.Debugger
ctrlDebuggerCode.UpdateLineColors();
}
private void OpenChildForm(Form frm)
{
this._childForms.Add(frm);
frm.FormClosed += (obj, args) => {
this._childForms.Remove((Form)obj);
};
frm.StartPosition = FormStartPosition.Manual;
frm.Left = this.Left + this.Width / 2 - frm.Width / 2;
frm.Top = this.Top + this.Height / 2 - frm.Height / 2;
frm.Show();
}
private void ResumeExecution()
{
ctrlConsoleStatus.ApplyChanges();
@ -483,7 +448,7 @@ namespace Mesen.GUI.Debugger
private void mnuMemoryViewer_Click(object sender, EventArgs e)
{
OpenChildForm(new frmMemoryViewer(() => { return _workspace; }));
DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryViewer);
}
private void BreakpointManager_BreakpointsChanged(object sender, EventArgs e)
@ -546,44 +511,34 @@ namespace Mesen.GUI.Debugger
protected override void OnFormClosing(FormClosingEventArgs e)
{
if(_childForms.Count > 0) {
foreach(Form frm in this._childForms.ToArray()) {
frm.Close();
}
e.Cancel = true;
tmrCdlRatios.Stop();
this.BeginInvoke((Action)(() => {
this.Close();
}));
} else {
tmrCdlRatios.Stop();
LabelManager.OnLabelUpdated -= LabelManager_OnLabelUpdated;
BreakpointManager.BreakpointsChanged -= BreakpointManager_BreakpointsChanged;
ctrlConsoleStatus.OnStateChanged -= ctrlConsoleStatus_OnStateChanged;
ctrlProfiler.OnFunctionSelected -= ctrlProfiler_OnFunctionSelected;
LabelManager.OnLabelUpdated -= LabelManager_OnLabelUpdated;
BreakpointManager.BreakpointsChanged -= BreakpointManager_BreakpointsChanged;
ctrlConsoleStatus.OnStateChanged -= ctrlConsoleStatus_OnStateChanged;
ctrlProfiler.OnFunctionSelected -= ctrlProfiler_OnFunctionSelected;
if(_notifListener != null) {
_notifListener.Dispose();
_notifListener = null;
}
InteropEmu.DebugRelease();
ConfigManager.Config.DebugInfo.WindowWidth = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Width : this.Width;
ConfigManager.Config.DebugInfo.WindowHeight = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Height : this.Height;
ConfigManager.Config.DebugInfo.TopPanelHeight = this.splitContainer.GetSplitterDistance();
ConfigManager.Config.DebugInfo.LeftPanelWidth = this.ctrlSplitContainerTop.GetSplitterDistance();
ConfigManager.ApplyChanges();
SaveWorkspace();
if(_notifListener != null) {
_notifListener.Dispose();
_notifListener = null;
}
base.OnFormClosing(e);
InteropEmu.DebugSetFlags(0);
InteropEmu.DebugSetBreakpoints(new InteropBreakpoint[0], 0);
InteropEmu.DebugRun();
ConfigManager.Config.DebugInfo.WindowWidth = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Width : this.Width;
ConfigManager.Config.DebugInfo.WindowHeight = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Height : this.Height;
ConfigManager.Config.DebugInfo.TopPanelHeight = this.splitContainer.GetSplitterDistance();
ConfigManager.Config.DebugInfo.LeftPanelWidth = this.ctrlSplitContainerTop.GetSplitterDistance();
ConfigManager.ApplyChanges();
DebugWorkspaceManager.SaveWorkspace();
}
private void mnuNametableViewer_Click(object sender, EventArgs e)
{
OpenChildForm(new frmPpuViewer());
DebugWindowManager.OpenDebugWindow(DebugWindow.PpuViewer);
}
private void ctrlCallstack_FunctionSelected(object sender, EventArgs e)
@ -639,15 +594,7 @@ namespace Mesen.GUI.Debugger
private void mnuTraceLogger_Click(object sender, EventArgs e)
{
if(_traceLogger == null) {
_traceLogger = new frmTraceLogger();
_traceLogger.FormClosed += (s, evt) => {
_traceLogger = null;
};
OpenChildForm(_traceLogger);
} else {
_traceLogger.Focus();
}
DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
}
private void mnuPpuPartialDraw_Click(object sender, EventArgs e)
@ -749,7 +696,7 @@ namespace Mesen.GUI.Debugger
private void LabelManager_OnLabelUpdated(object sender, EventArgs e)
{
SaveWorkspace();
DebugWorkspaceManager.SaveWorkspace();
ctrlLabelList.UpdateLabelList();
ctrlFunctionList.UpdateFunctionList(true);
UpdateDebugger(false);
@ -763,11 +710,7 @@ namespace Mesen.GUI.Debugger
private void mnuResetWorkspace_Click(object sender, EventArgs e)
{
if(MessageBox.Show("This operation will empty the watch window, remove all breakpoints, and reset labels to their default state." + Environment.NewLine + "Are you sure?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) {
_workspace.Breakpoints = new List<Breakpoint>();
_workspace.Labels = new List<CodeLabel>();
_workspace.WatchValues = new List<string>();
_workspace.Save();
_workspace = null;
DebugWorkspaceManager.ResetWorkspace();
LabelManager.ResetLabels();
UpdateWorkspace();
UpdateDebugger(false);
@ -919,13 +862,7 @@ namespace Mesen.GUI.Debugger
private void OpenAssembler(string code, UInt16 startAddress, UInt16 blockLength = 0)
{
frmAssembler assembler = new frmAssembler(code, startAddress, blockLength);
assembler.FormClosed += (s, e) => {
if(assembler.DialogResult == DialogResult.OK) {
this.UpdateDebugger(false);
}
};
OpenChildForm(assembler);
DebugWindowManager.OpenDebugWindow(DebugWindow.Assembler);
}
private void mnuAssembler_Click(object sender, EventArgs e)

View File

@ -20,13 +20,12 @@ namespace Mesen.GUI.Debugger
{
private InteropEmu.NotificationListener _notifListener;
private DebugMemoryType _memoryType = DebugMemoryType.CpuMemory;
private Func<DebugWorkspace> _getWorkspace;
private int _previousIndex = -1;
private DebugWorkspace _previousWorkspace;
public frmMemoryViewer(Func<DebugWorkspace> getWorkspace)
public frmMemoryViewer()
{
InitializeComponent();
this._getWorkspace = getWorkspace;
}
protected override void OnLoad(EventArgs e)
@ -61,10 +60,17 @@ namespace Mesen.GUI.Debugger
this.mnuShowCharacters.CheckedChanged += new EventHandler(this.mnuShowCharacters_CheckedChanged);
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
DebugWorkspaceManager.SaveWorkspace();
}
void InitTblMappings()
{
if(this._getWorkspace().TblMappings != null && this._getWorkspace().TblMappings.Count > 0) {
var tblDict = TblLoader.ToDictionary(this._getWorkspace().TblMappings.ToArray());
DebugWorkspace workspace = DebugWorkspaceManager.GetWorkspace();
if(workspace.TblMappings != null && workspace.TblMappings.Count > 0) {
var tblDict = TblLoader.ToDictionary(workspace.TblMappings.ToArray());
if(tblDict != null) {
this.ctrlHexViewer.ByteCharConverter = new TblByteCharConverter(tblDict);
}
@ -119,14 +125,12 @@ namespace Mesen.GUI.Debugger
this.RefreshData();
}
int _previousIndex = -1;
DebugWorkspace _previousWorkspace;
private void RefreshData()
{
if(this._getWorkspace() != this._previousWorkspace) {
if(DebugWorkspaceManager.GetWorkspace() != this._previousWorkspace) {
this.InitTblMappings();
_previousWorkspace = DebugWorkspaceManager.GetWorkspace();
}
_previousWorkspace = this._getWorkspace();
if(this.tabMain.SelectedTab == this.tpgAccessCounters) {
this.ctrlMemoryAccessCounters.RefreshData();
@ -280,7 +284,7 @@ namespace Mesen.GUI.Debugger
if(tblDict == null) {
MessageBox.Show("Could not load TBL file. The file selected file appears to be invalid.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
this._getWorkspace().TblMappings = new List<string>(fileContents);
DebugWorkspaceManager.GetWorkspace().TblMappings = new List<string>(fileContents);
this.ctrlHexViewer.ByteCharConverter = new TblByteCharConverter(tblDict);
this.mnuShowCharacters.Checked = true;
}
@ -289,7 +293,7 @@ namespace Mesen.GUI.Debugger
private void mnuResetTblMappings_Click(object sender, EventArgs e)
{
this._getWorkspace().TblMappings = null;
DebugWorkspaceManager.GetWorkspace().TblMappings = null;
this.ctrlHexViewer.ByteCharConverter = null;
}
@ -437,7 +441,7 @@ namespace Mesen.GUI.Debugger
}
mnuEditLabel.Enabled = !disableEditLabel && (this._memoryType == DebugMemoryType.CpuMemory || this.GetAddressType().HasValue);
mnuEditBreakpoint.Enabled = this._memoryType == DebugMemoryType.CpuMemory || this._memoryType == DebugMemoryType.PpuMemory;
mnuEditBreakpoint.Enabled = (this._memoryType == DebugMemoryType.CpuMemory || this._memoryType == DebugMemoryType.PpuMemory) && DebugWindowManager.GetDebugger() != null;
mnuAddWatch.Enabled = this._memoryType == DebugMemoryType.CpuMemory;
mnuFreeze.Enabled = this._memoryType == DebugMemoryType.CpuMemory;
};

View File

@ -54,6 +54,12 @@ namespace Mesen.GUI.Debugger
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
this._notifListener.OnNotification -= this._notifListener_OnNotification;
}
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
{
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {

View File

@ -153,6 +153,9 @@ namespace Mesen.GUI.Debugger
return;
}
//Make sure labels are up to date
DebugWorkspaceManager.GetWorkspace();
_refreshRunning = true;
SetOptions();
Task.Run(() => {

View File

@ -347,6 +347,8 @@
<Control ID="chkSingleInstance">Permet només una sola instància de Mesen alhora</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Cerca actualitzacions automàticament</Control>
<Control ID="chkDeveloperMode">Enable developer mode</Control>
<Control ID="lblPauseBackgroundSettings">Comportament en segon pla</Control>
<Control ID="lblMiscSettings">Configuracions diverses</Control>
<Control ID="chkAutoHideMenu">Amaga la barra de menú automàticament</Control>

View File

@ -347,6 +347,8 @@
<Control ID="chkSingleInstance">Permitir una sola copia de Mesen a la vez</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Buscar actualizaciones automáticamente</Control>
<Control ID="chkDeveloperMode">Enable developer mode</Control>
<Control ID="lblPauseBackgroundSettings">Pausa/Configuración en segundo plano</Control>
<Control ID="lblMiscSettings">Configuraciones varias</Control>
<Control ID="chkAutoHideMenu">Ocultar barra de menú automáticamente</Control>

View File

@ -350,6 +350,8 @@
<Control ID="chkSingleInstance">Permettre une seule copie de Mesen à la fois</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Rechercher des mises-à-jour automatiquement</Control>
<Control ID="chkDeveloperMode">Activer le mode développeur</Control>
<Control ID="lblPauseBackgroundSettings">Options d'arrière-plan et pause</Control>
<Control ID="lblMiscSettings">Options diverses</Control>
<Control ID="chkAutoHideMenu">Cacher la barre de menu automatiquement</Control>

View File

@ -348,6 +348,8 @@
<Control ID="lblDisplayLanguage">言語:</Control>
<Control ID="chkSingleInstance">Mesenを単一インスタンスモードにする</Control>
<Control ID="chkAutomaticallyCheckForUpdates">自動的にアップデートを確認</Control>
<Control ID="chkDeveloperMode">開発者モードを有効にする</Control>
<Control ID="lblPauseBackgroundSettings">ポーズ・バックグラウンド設定</Control>
<Control ID="lblMiscSettings">その他</Control>

View File

@ -347,6 +347,8 @@
<Control ID="chkSingleInstance">Permitir apenas uma cópia de Mesen por vez</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Buscar atualizações automaticamente</Control>
<Control ID="chkDeveloperMode">Enable developer mode</Control>
<Control ID="lblPauseBackgroundSettings">Pausar/Configurações em segundo plano</Control>
<Control ID="lblMiscSettings">Configurações diversas</Control>
<Control ID="chkAutoHideMenu">Ocultar automaticamente a barra de menus</Control>

View File

@ -349,6 +349,8 @@
<Control ID="chkSingleInstance">Запускать только одну копию Mesen</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Автоматически проверять обновления</Control>
<Control ID="chkDeveloperMode">Enable developer mode</Control>
<Control ID="lblPauseBackgroundSettings">Pause/Background Settings</Control>
<Control ID="lblMiscSettings">Misc. Settings</Control>
<Control ID="chkAutoHideMenu">Automatically hide menu bar</Control>

View File

@ -349,6 +349,8 @@
<Control ID="chkSingleInstance">Запускати тільки одну копію Mesen</Control>
<Control ID="chkAutomaticallyCheckForUpdates">Автоматично перевіряти оновлення</Control>
<Control ID="chkDeveloperMode">Enable developer mode</Control>
<Control ID="lblPauseBackgroundSettings">Пауза/Фонові настройки</Control>
<Control ID="lblMiscSettings">Різнi настройки</Control>
<Control ID="chkAutoHideMenu">Автоматично приховувати панель меню</Control>

View File

@ -49,6 +49,7 @@ namespace Mesen.GUI.Forms.Config
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
this.btnOpenMesenFolder = new System.Windows.Forms.Button();
this.btnResetSettings = new System.Windows.Forms.Button();
this.chkConfirmExitResetPower = new System.Windows.Forms.CheckBox();
this.tabMain = new System.Windows.Forms.TabControl();
this.tpgGeneral = new System.Windows.Forms.TabPage();
this.tpgShortcuts = new System.Windows.Forms.TabPage();
@ -140,7 +141,7 @@ namespace Mesen.GUI.Forms.Config
this.lblUiDisplaySettings = new System.Windows.Forms.Label();
this.lblGameSelectionScreenSettings = new System.Windows.Forms.Label();
this.tmrSyncDateTime = new System.Windows.Forms.Timer(this.components);
this.chkConfirmExitResetPower = new System.Windows.Forms.CheckBox();
this.chkDeveloperMode = new System.Windows.Forms.CheckBox();
this.tlpMain.SuspendLayout();
this.flowLayoutPanel2.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
@ -191,6 +192,7 @@ namespace Mesen.GUI.Forms.Config
//
this.tlpMain.ColumnCount = 1;
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpMain.Controls.Add(this.chkDeveloperMode, 0, 13);
this.tlpMain.Controls.Add(this.lblPauseBackgroundSettings, 0, 3);
this.tlpMain.Controls.Add(this.chkSingleInstance, 0, 2);
this.tlpMain.Controls.Add(this.chkAutomaticallyCheckForUpdates, 0, 1);
@ -203,12 +205,12 @@ namespace Mesen.GUI.Forms.Config
this.tlpMain.Controls.Add(this.chkAllowBackgroundInput, 0, 7);
this.tlpMain.Controls.Add(this.chkPauseWhenInBackground, 0, 6);
this.tlpMain.Controls.Add(this.chkPauseOnMovieEnd, 0, 5);
this.tlpMain.Controls.Add(this.tableLayoutPanel5, 0, 14);
this.tlpMain.Controls.Add(this.tableLayoutPanel5, 0, 15);
this.tlpMain.Controls.Add(this.chkConfirmExitResetPower, 0, 11);
this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpMain.Location = new System.Drawing.Point(3, 3);
this.tlpMain.Name = "tlpMain";
this.tlpMain.RowCount = 15;
this.tlpMain.RowCount = 16;
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
@ -222,6 +224,7 @@ namespace Mesen.GUI.Forms.Config
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpMain.Size = new System.Drawing.Size(483, 353);
@ -418,6 +421,17 @@ namespace Mesen.GUI.Forms.Config
this.btnResetSettings.UseVisualStyleBackColor = true;
this.btnResetSettings.Click += new System.EventHandler(this.btnResetSettings_Click);
//
// chkConfirmExitResetPower
//
this.chkConfirmExitResetPower.AutoSize = true;
this.chkConfirmExitResetPower.Location = new System.Drawing.Point(13, 253);
this.chkConfirmExitResetPower.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
this.chkConfirmExitResetPower.Name = "chkConfirmExitResetPower";
this.chkConfirmExitResetPower.Size = new System.Drawing.Size(293, 17);
this.chkConfirmExitResetPower.TabIndex = 25;
this.chkConfirmExitResetPower.Text = "Display confirmation dialog before reset/power cycle/exit";
this.chkConfirmExitResetPower.UseVisualStyleBackColor = true;
//
// tabMain
//
this.tabMain.Controls.Add(this.tpgGeneral);
@ -866,23 +880,23 @@ namespace Mesen.GUI.Forms.Config
this.nudNsfMoveToNextTrackTime.Location = new System.Drawing.Point(129, 3);
this.nudNsfMoveToNextTrackTime.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.nudNsfMoveToNextTrackTime.Maximum = new decimal(new int[] {
999,
0,
0,
0});
999,
0,
0,
0});
this.nudNsfMoveToNextTrackTime.Minimum = new decimal(new int[] {
5,
0,
0,
0});
5,
0,
0,
0});
this.nudNsfMoveToNextTrackTime.Name = "nudNsfMoveToNextTrackTime";
this.nudNsfMoveToNextTrackTime.Size = new System.Drawing.Size(44, 20);
this.nudNsfMoveToNextTrackTime.TabIndex = 3;
this.nudNsfMoveToNextTrackTime.Value = new decimal(new int[] {
5,
0,
0,
0});
5,
0,
0,
0});
//
// lblNsfSeconds
//
@ -1598,16 +1612,16 @@ namespace Mesen.GUI.Forms.Config
this.tmrSyncDateTime.Enabled = true;
this.tmrSyncDateTime.Tick += new System.EventHandler(this.tmrSyncDateTime_Tick);
//
// chkConfirmExitResetPower
// chkDeveloperMode
//
this.chkConfirmExitResetPower.AutoSize = true;
this.chkConfirmExitResetPower.Location = new System.Drawing.Point(13, 253);
this.chkConfirmExitResetPower.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
this.chkConfirmExitResetPower.Name = "chkConfirmExitResetPower";
this.chkConfirmExitResetPower.Size = new System.Drawing.Size(293, 17);
this.chkConfirmExitResetPower.TabIndex = 25;
this.chkConfirmExitResetPower.Text = "Display confirmation dialog before reset/power cycle/exit";
this.chkConfirmExitResetPower.UseVisualStyleBackColor = true;
this.chkDeveloperMode.AutoSize = true;
this.chkDeveloperMode.Location = new System.Drawing.Point(13, 299);
this.chkDeveloperMode.Margin = new System.Windows.Forms.Padding(13, 3, 3, 3);
this.chkDeveloperMode.Name = "chkDeveloperMode";
this.chkDeveloperMode.Size = new System.Drawing.Size(138, 17);
this.chkDeveloperMode.TabIndex = 26;
this.chkDeveloperMode.Text = "Enable developer mode";
this.chkDeveloperMode.UseVisualStyleBackColor = true;
//
// frmPreferences
//
@ -1797,5 +1811,6 @@ namespace Mesen.GUI.Forms.Config
private ctrlPathSelection psScreenshots;
private ctrlPathSelection psAvi;
private System.Windows.Forms.CheckBox chkConfirmExitResetPower;
private System.Windows.Forms.CheckBox chkDeveloperMode;
}
}

View File

@ -26,6 +26,8 @@ namespace Mesen.GUI.Forms.Config
AddBinding("AutomaticallyCheckForUpdates", chkAutomaticallyCheckForUpdates);
AddBinding("SingleInstance", chkSingleInstance);
AddBinding("AutoLoadIpsPatches", chkAutoLoadIps);
AddBinding("DeveloperMode", chkDeveloperMode);
AddBinding("AssociateNesFiles", chkNesFormat);
AddBinding("AssociateFdsFiles", chkFdsFormat);
AddBinding("AssociateMmoFiles", chkMmoFormat);

View File

@ -179,6 +179,12 @@ namespace Mesen.GUI.Forms
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebug = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAssembler = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebugDebugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuHelp = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCheckForUpdates = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem20 = new System.Windows.Forms.ToolStripSeparator();
@ -186,6 +192,8 @@ namespace Mesen.GUI.Forms
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuHelpWindow = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripSeparator();
this.mnuEditHeader = new System.Windows.Forms.ToolStripMenuItem();
this.panelRenderer.SuspendLayout();
this.panelInfo.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picIcon)).BeginInit();
@ -299,6 +307,7 @@ namespace Mesen.GUI.Forms
this.mnuGame,
this.mnuOptions,
this.mnuTools,
this.mnuDebug,
this.mnuHelp});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
@ -1432,6 +1441,65 @@ namespace Mesen.GUI.Forms
this.mnuTakeScreenshot.Text = "Take Screenshot";
this.mnuTakeScreenshot.Click += new System.EventHandler(this.mnuTakeScreenshot_Click);
//
// mnuDebug
//
this.mnuDebug.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuAssembler,
this.mnuDebugDebugger,
this.mnuMemoryViewer,
this.mnuPpuViewer,
this.mnuTraceLogger,
this.toolStripMenuItem25,
this.mnuEditHeader});
this.mnuDebug.Name = "mnuDebug";
this.mnuDebug.Size = new System.Drawing.Size(54, 20);
this.mnuDebug.Text = "Debug";
//
// mnuAssembler
//
this.mnuAssembler.Image = global::Mesen.GUI.Properties.Resources.Chip;
this.mnuAssembler.Name = "mnuAssembler";
this.mnuAssembler.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.K)));
this.mnuAssembler.Size = new System.Drawing.Size(196, 22);
this.mnuAssembler.Text = "Assembler";
this.mnuAssembler.Click += new System.EventHandler(this.mnuAssembler_Click);
//
// mnuDebugDebugger
//
this.mnuDebugDebugger.Image = global::Mesen.GUI.Properties.Resources.Bug;
this.mnuDebugDebugger.Name = "mnuDebugDebugger";
this.mnuDebugDebugger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.D)));
this.mnuDebugDebugger.Size = new System.Drawing.Size(196, 22);
this.mnuDebugDebugger.Text = "Debugger";
this.mnuDebugDebugger.Click += new System.EventHandler(this.mnuDebugDebugger_Click);
//
// mnuMemoryViewer
//
this.mnuMemoryViewer.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuMemoryViewer.Name = "mnuMemoryViewer";
this.mnuMemoryViewer.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.M)));
this.mnuMemoryViewer.Size = new System.Drawing.Size(196, 22);
this.mnuMemoryViewer.Text = "Memory Tools";
this.mnuMemoryViewer.Click += new System.EventHandler(this.mnuMemoryViewer_Click);
//
// mnuPpuViewer
//
this.mnuPpuViewer.Image = global::Mesen.GUI.Properties.Resources.Video;
this.mnuPpuViewer.Name = "mnuPpuViewer";
this.mnuPpuViewer.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P)));
this.mnuPpuViewer.Size = new System.Drawing.Size(196, 22);
this.mnuPpuViewer.Text = "PPU Viewer";
this.mnuPpuViewer.Click += new System.EventHandler(this.mnuPpuViewer_Click);
//
// mnuTraceLogger
//
this.mnuTraceLogger.Image = global::Mesen.GUI.Properties.Resources.LogWindow;
this.mnuTraceLogger.Name = "mnuTraceLogger";
this.mnuTraceLogger.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.L)));
this.mnuTraceLogger.Size = new System.Drawing.Size(196, 22);
this.mnuTraceLogger.Text = "Trace Logger";
this.mnuTraceLogger.Click += new System.EventHandler(this.mnuTraceLogger_Click);
//
// mnuHelp
//
this.mnuHelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -1486,6 +1554,19 @@ namespace Mesen.GUI.Forms
this.mnuAbout.Text = "About";
this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click);
//
// toolStripMenuItem25
//
this.toolStripMenuItem25.Name = "toolStripMenuItem25";
this.toolStripMenuItem25.Size = new System.Drawing.Size(193, 6);
//
// mnuEditHeader
//
this.mnuEditHeader.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditHeader.Name = "mnuEditHeader";
this.mnuEditHeader.Size = new System.Drawing.Size(196, 22);
this.mnuEditHeader.Text = "Edit iNES Header";
this.mnuEditHeader.Click += new System.EventHandler(this.mnuEditHeader_Click);
//
// frmMain
//
this.AllowDrop = true;
@ -1670,6 +1751,14 @@ namespace Mesen.GUI.Forms
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem24;
private System.Windows.Forms.ToolStripMenuItem mnuPowerOff;
private System.Windows.Forms.ToolStripMenuItem mnuHdPackEditor;
private System.Windows.Forms.ToolStripMenuItem mnuDebug;
private System.Windows.Forms.ToolStripMenuItem mnuAssembler;
private System.Windows.Forms.ToolStripMenuItem mnuDebugDebugger;
private System.Windows.Forms.ToolStripMenuItem mnuMemoryViewer;
private System.Windows.Forms.ToolStripMenuItem mnuPpuViewer;
private System.Windows.Forms.ToolStripMenuItem mnuTraceLogger;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem25;
private System.Windows.Forms.ToolStripMenuItem mnuEditHeader;
}
}

View File

@ -17,14 +17,38 @@ namespace Mesen.GUI.Forms
{
private void mnuDebugger_Click(object sender, EventArgs e)
{
if(_debugger == null) {
_debugger = new frmDebugger();
_debugger.FormClosed += (obj, args) => {
_debugger = null;
};
_debugger.Show();
} else {
_debugger.Focus();
DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger);
}
private void mnuDebugDebugger_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger);
}
private void mnuTraceLogger_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
}
private void mnuPpuViewer_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.PpuViewer);
}
private void mnuMemoryViewer_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryViewer);
}
private void mnuAssembler_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.Assembler);
}
private void mnuEditHeader_Click(object sender, EventArgs e)
{
using(frmEditHeader frm = new frmEditHeader()) {
frm.ShowDialog(sender, this);
}
}

View File

@ -29,7 +29,6 @@ namespace Mesen.GUI.Forms
private InteropEmu.NotificationListener _notifListener;
private Thread _emuThread;
private frmDebugger _debugger;
private frmLogWindow _logWindow;
private frmCheatList _cheatListWindow;
private frmHdPackEditor _hdPackEditorWindow;
@ -58,6 +57,8 @@ namespace Mesen.GUI.Forms
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
Version currentVersion = new Version(InteropEmu.GetMesenVersion());
lblVersion.Text = currentVersion.ToString();
@ -156,9 +157,6 @@ namespace Mesen.GUI.Forms
if(ConfigManager.Config.WindowLocation.HasValue) {
this.StartPosition = FormStartPosition.Manual;
this.Location = ConfigManager.Config.WindowLocation.Value;
} else {
//First launch
this.StartPosition = FormStartPosition.CenterScreen;
}
if(ConfigManager.Config.PreferenceInfo.CloudSaveIntegration) {
@ -218,9 +216,7 @@ namespace Mesen.GUI.Forms
_notifListener.Dispose();
_notifListener = null;
}
if(_debugger != null) {
_debugger.Close();
}
DebugWindowManager.CloseAll();
ConfigManager.Config.EmulationInfo.EmulationSpeed = InteropEmu.GetEmulationSpeed();
if(this.WindowState == FormWindowState.Normal) {
@ -400,6 +396,11 @@ namespace Mesen.GUI.Forms
this.BeginInvoke((MethodInvoker)(() => {
UpdateViewerSize();
}));
if(ConfigManager.Config.PreferenceInfo.DeveloperMode) {
//Preload workspace in the background to be able to open debugging tools faster
Task.Run(() => { DebugWorkspace.GetWorkspace(); });
}
break;
case InteropEmu.ConsoleNotificationType.PpuFrameDone:
@ -499,8 +500,19 @@ namespace Mesen.GUI.Forms
if(this.InvokeRequired) {
this.BeginInvoke((MethodInvoker)(() => this.UpdateMenus()));
} else {
panelInfo.Visible = _emuThread == null;
ctrlRecentGames.Visible = _emuThread == null;
bool running = _emuThread != null;
bool devMode = ConfigManager.Config.PreferenceInfo.DeveloperMode;
mnuDebug.Visible = devMode;
mnuAssembler.Enabled = running;
mnuMemoryViewer.Enabled = running;
mnuPpuViewer.Enabled = running;
mnuTraceLogger.Enabled = running;
mnuDebugDebugger.Enabled = running;
mnuEditHeader.Enabled = running;
panelInfo.Visible = !running;
ctrlRecentGames.Visible = !running;
ctrlLoading.Visible = (_romLoadCounter > 0);
@ -509,9 +521,9 @@ namespace Mesen.GUI.Forms
bool isNetPlayClient = InteropEmu.IsConnected();
mnuPause.Enabled = mnuPowerCycle.Enabled = mnuReset.Enabled = mnuPowerOff.Enabled = (_emuThread != null && !isNetPlayClient);
mnuSaveState.Enabled = (_emuThread != null && !isNetPlayClient && !InteropEmu.IsNsf());
mnuLoadState.Enabled = (_emuThread != null && !isNetPlayClient && !InteropEmu.IsNsf() && !InteropEmu.MoviePlaying() && !InteropEmu.MovieRecording());
mnuPause.Enabled = mnuPowerCycle.Enabled = mnuReset.Enabled = mnuPowerOff.Enabled = (running && !isNetPlayClient);
mnuSaveState.Enabled = (running && !isNetPlayClient && !InteropEmu.IsNsf());
mnuLoadState.Enabled = (running && !isNetPlayClient && !InteropEmu.IsNsf() && !InteropEmu.MoviePlaying() && !InteropEmu.MovieRecording());
mnuPause.Text = InteropEmu.IsPaused() ? ResourceHelper.GetMessage("Resume") : ResourceHelper.GetMessage("Pause");
mnuPause.Image = InteropEmu.IsPaused() ? _playButton : _pauseButton;
@ -556,35 +568,36 @@ namespace Mesen.GUI.Forms
bool moviePlaying = InteropEmu.MoviePlaying();
bool movieRecording = InteropEmu.MovieRecording();
mnuPlayMovie.Enabled = !netPlay && !moviePlaying && !movieRecording;
mnuStopMovie.Enabled = _emuThread != null && !netPlay && (moviePlaying || movieRecording);
mnuRecordFrom.Enabled = _emuThread != null && !moviePlaying && !movieRecording;
mnuRecordFromStart.Enabled = _emuThread != null && !isNetPlayClient && !moviePlaying && !movieRecording;
mnuRecordFromNow.Enabled = _emuThread != null && !moviePlaying && !movieRecording;
mnuStopMovie.Enabled = running && !netPlay && (moviePlaying || movieRecording);
mnuRecordFrom.Enabled = running && !moviePlaying && !movieRecording;
mnuRecordFromStart.Enabled = running && !isNetPlayClient && !moviePlaying && !movieRecording;
mnuRecordFromNow.Enabled = running && !moviePlaying && !movieRecording;
bool waveRecording = InteropEmu.WaveIsRecording();
mnuWaveRecord.Enabled = _emuThread != null && !waveRecording;
mnuWaveStop.Enabled = _emuThread != null && waveRecording;
mnuWaveRecord.Enabled = running && !waveRecording;
mnuWaveStop.Enabled = running && waveRecording;
bool aviRecording = InteropEmu.AviIsRecording();
mnuAviRecord.Enabled = _emuThread != null && !aviRecording;
mnuAviStop.Enabled = _emuThread != null && aviRecording;
mnuAviRecord.Enabled = running && !aviRecording;
mnuAviStop.Enabled = running && aviRecording;
mnuVideoRecorder.Enabled = !_isNsfPlayerMode;
bool testRecording = InteropEmu.RomTestRecording();
mnuTestRun.Enabled = !netPlay && !moviePlaying && !movieRecording;
mnuTestStopRecording.Enabled = _emuThread != null && testRecording;
mnuTestRecordStart.Enabled = _emuThread != null && !isNetPlayClient && !moviePlaying && !movieRecording;
mnuTestRecordNow.Enabled = _emuThread != null && !moviePlaying && !movieRecording;
mnuTestStopRecording.Enabled = running && testRecording;
mnuTestRecordStart.Enabled = running && !isNetPlayClient && !moviePlaying && !movieRecording;
mnuTestRecordNow.Enabled = running && !moviePlaying && !movieRecording;
mnuTestRecordMovie.Enabled = !netPlay && !moviePlaying && !movieRecording;
mnuTestRecordTest.Enabled = !netPlay && !moviePlaying && !movieRecording;
mnuTestRecordFrom.Enabled = (mnuTestRecordStart.Enabled || mnuTestRecordNow.Enabled || mnuTestRecordMovie.Enabled || mnuTestRecordTest.Enabled);
mnuDebugger.Enabled = !netPlay && _emuThread != null;
mnuHdPackEditor.Enabled = !netPlay && _emuThread != null;
mnuDebugger.Visible = !devMode;
mnuDebugger.Enabled = !netPlay && running && !devMode;
mnuHdPackEditor.Enabled = !netPlay && running;
mnuTakeScreenshot.Enabled = _emuThread != null && !InteropEmu.IsNsf();
mnuTakeScreenshot.Enabled = running && !InteropEmu.IsNsf();
mnuNetPlay.Enabled = !InteropEmu.IsNsf();
if(_emuThread != null && InteropEmu.IsNsf()) {
if(running && InteropEmu.IsNsf()) {
mnuPowerCycle.Enabled = false;
mnuMovies.Enabled = mnuPlayMovie.Enabled = mnuStopMovie.Enabled = mnuRecordFrom.Enabled = mnuRecordFromStart.Enabled = mnuRecordFromNow.Enabled = false;
}
@ -638,7 +651,8 @@ namespace Mesen.GUI.Forms
private void PauseEmu()
{
if(InteropEmu.DebugIsDebuggerRunning()) {
frmDebugger debugger = DebugWindowManager.GetDebugger();
if(debugger != null) {
InteropEmu.DebugStep(1);
} else {
if(InteropEmu.IsPaused()) {

View File

@ -395,6 +395,8 @@
<DependentUpon>ctrlPaletteDisplay.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\DbgImporter.cs" />
<Compile Include="Debugger\DebugWindowManager.cs" />
<Compile Include="Debugger\DebugWorkspaceManager.cs" />
<Compile Include="Debugger\frmAssembler.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -1109,6 +1109,7 @@ namespace Mesen.GUI
DisassembleEverythingButData = 0x20,
BreakOnBrk = 0x40,
BreakOnUnofficialOpCode = 0x80,
DebuggerWindowEnabled = 0x100,
}
public struct InteropRomInfo