Debugger: LUA scripting fixes, script window & assembler window improvements

This commit is contained in:
Souryo 2017-09-01 14:57:02 -04:00
parent 4052874cf5
commit b80d788346
17 changed files with 416 additions and 96 deletions

View file

@ -162,7 +162,6 @@ void CheatManager::ApplyRamCodes(uint16_t addr, uint8_t &value)
void CheatManager::ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize)
{
Console::Pause();
for(uint32_t i = 0, len = i < Instance->_absoluteCheatCodes.size(); i < len; i++) {
CodeInfo code = Instance->_absoluteCheatCodes[i];
if(code.Address < prgSize) {
@ -171,7 +170,6 @@ void CheatManager::ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize)
}
}
}
Console::Resume();
}
vector<CodeInfo> CheatManager::GetCheats()

View file

@ -370,10 +370,6 @@ void Console::Run()
_lagCounter++;
}
if(_debugger) {
_debugger->ProcessEvent(EventType::StartFrame);
}
_rewindManager->ProcessEndOfFrame();
EmulationSettings::DisableOverclocking(_disableOcNextFrame || NsfMapper::GetInstance());
_disableOcNextFrame = false;
@ -419,6 +415,10 @@ void Console::Run()
MessageManager::SendNotification(ConsoleNotificationType::GameResumed);
}
if(_debugger) {
_debugger->ProcessEvent(EventType::StartFrame);
}
//Get next target time, and adjust based on whether we are ahead or behind
double timeLag = EmulationSettings::GetEmulationSpeed() == 0 ? 0 : clockTimer.GetElapsedMS() - targetTime;
UpdateNesModel(true);

View file

@ -14,7 +14,8 @@ public:
_debugger = debugger;
if(!debugger->IsExecutionStopped()) {
debugger->Step(1, false);
debugger->SetSendNotificationFlag(false);
debugger->Step(1);
while(!debugger->IsExecutionStopped()) {}
_needResume = true;
}
@ -24,6 +25,7 @@ public:
{
if(_needResume) {
_debugger->Run();
_debugger->SetSendNotificationFlag(true);
}
}
};

View file

@ -58,7 +58,6 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_suspendCount = 0;
_lastInstruction = 0;
_sendNotification = false;
_currentReadAddr = nullptr;
_currentReadValue = nullptr;
@ -584,8 +583,6 @@ bool Debugger::SleepUntilResume()
}
}
_sendNotification = true;
while(stepCount == 0 && !_stopFlag && _suspendCount == 0) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
stepCount = _stepCount.load();
@ -662,7 +659,6 @@ void Debugger::Step(uint32_t count, bool sendNotification)
_stepOverAddr = -1;
_stepCycleCount = -1;
_ppuStepCount = -1;
_sendNotification = sendNotification;
_stepCount = count;
}
@ -702,6 +698,11 @@ void Debugger::StepBack()
}
}
void Debugger::SetSendNotificationFlag(bool enabled)
{
_sendNotification = enabled;
}
void Debugger::Run()
{
//Resume execution after a breakpoint has been hit

View file

@ -162,6 +162,7 @@ public:
void StepOut();
void StepBack();
void Run();
void SetSendNotificationFlag(bool enabled);
bool LoadCdlFile(string cdlFilepath);
void ResetCdl();

View file

@ -80,11 +80,10 @@ struct OperationInfo
enum class EventType
{
Power = 0,
Reset = 1,
Nmi = 2,
Irq = 3,
StartFrame = 4,
EndFrame = 5,
CodeBreak = 6
Reset = 0,
Nmi = 1,
Irq = 2,
StartFrame = 3,
EndFrame = 4,
CodeBreak = 5
};

View file

@ -120,9 +120,8 @@ int LuaApi::GetLibrary(lua_State *lua)
lua_pushintvalue(ppuWrite, CallbackType::PpuWrite);
lua_settable(lua, -3);
lua_pushliteral(lua, "eventCallbackType");
lua_pushliteral(lua, "eventType");
lua_newtable(lua);
lua_pushintvalue(power, EventType::Power);
lua_pushintvalue(reset, EventType::Reset);
lua_pushintvalue(nmi, EventType::Nmi);
lua_pushintvalue(irq, EventType::Irq);
@ -131,6 +130,13 @@ int LuaApi::GetLibrary(lua_State *lua)
lua_pushintvalue(codeBreak, EventType::CodeBreak);
lua_settable(lua, -3);
lua_pushliteral(lua, "executeCountType");
lua_newtable(lua);
lua_pushintvalue(cpuCycles, ExecuteCountType::CpuCycles);
lua_pushintvalue(cpuInstructions, ExecuteCountType::CpuInstructions);
lua_pushintvalue(ppuCycles, ExecuteCountType::PpuCycles);
lua_settable(lua, -3);
return 1;
}
@ -276,9 +282,10 @@ int LuaApi::RegisterEventCallback(lua_State *lua)
EventType type = (EventType)l.ReadInteger();
int reference = l.GetReference();
checkparams();
errorCond(type < EventType::Power || type > EventType::CodeBreak, "the specified type is invalid");
errorCond(type < EventType::Reset || type > EventType::CodeBreak, "the specified type is invalid");
errorCond(reference == LUA_NOREF, "the specified function could not be found");
_context->RegisterEventCallback(type, reference);
l.Return(reference);
return l.ReturnCount();
}
@ -288,7 +295,7 @@ int LuaApi::UnregisterEventCallback(lua_State *lua)
EventType type = (EventType)l.ReadInteger();
int reference = l.ReadInteger();
checkparams();
errorCond(type < EventType::Power || type > EventType::CodeBreak, "the specified type is invalid");
errorCond(type < EventType::Reset || type > EventType::CodeBreak, "the specified type is invalid");
errorCond(reference == LUA_NOREF, "function reference is invalid");
_context->UnregisterEventCallback(type, reference);
return l.ReturnCount();

View file

@ -167,7 +167,8 @@ namespace Mesen.GUI.Config
public int ScriptCodeWindowHeight = 0;
public List<string> RecentScripts = new List<string>();
public bool SaveScriptBeforeRun = true;
public bool AutoReloadScript = false;
public ScriptStartupBehavior ScriptStartupBehavior = ScriptStartupBehavior.ShowTutorial;
public bool AutoLoadLastScript = true;
public int ScriptZoom = 100;
public bool AssemblerCodeHighlighting = true;
@ -212,6 +213,14 @@ namespace Mesen.GUI.Config
}
}
public enum ScriptStartupBehavior
{
ShowTutorial = 0,
ShowBlankWindow = 1,
LoadLastScript = 2
}
public class XmlColor
{
private Color _color = Color.Black;

View file

@ -41,6 +41,14 @@ namespace Mesen.GUI.Debugger
frm.Show();
}
public static void OpenScriptWindow(bool forceBlank)
{
frmScript frm = new frmScript(forceBlank);
_openedWindows.Add(frm);
frm.FormClosed += Debugger_FormClosed;
frm.Show();
}
public static frmDebugger GetDebugger()
{
int index = _openedWindows.FindIndex((form) => form.GetType() == typeof(frmDebugger));

View file

@ -0,0 +1,49 @@
--This is an example script to give an idea of how scripting work
--Press F5 or click the Run button to execute it
--Scripts must be written in LUA (https://www.lua.org)
--This text editor contains an auto-complete feature for all Mesen-specific functions
--Typing "emu." will display a list containing every available API function to interact with Mesen
function printInfo()
--Get the emulation state
state = emu.getState()
--Get the mouse's state (x, y, left, right, middle)
mouseState = emu.getMouseState()
--Select colors based on whether the left button is held down
if mouseState.left == true then
for y = 0, 239 do
for x = 0, 255 do
--Remove red color from the entire screen (slow)
color = emu.getPixel(x, y)
emu.drawPixel(x, y, color & 0xFFFF, 1)
end
end
bgColor = 0xFF6020
fgColor = 0x4040FF
else
bgColor = 0x2060FF
fgColor = 0xFF4040
end
--Draw some rectangles and print some text
emu.drawRectangle(8, 8, 128, 24, bgColor, true, 1)
emu.drawRectangle(8, 8, 128, 24, fgColor, false, 1)
emu.drawString(12, 12, "Frame: " .. state.ppu.frameCount, 0xFFFFFF, bgColor, 1)
emu.drawString(12, 21, "CPU Cycle: " .. state.cpu.cycleCount, 0xFFFFFF, bgColor, 1)
emu.drawRectangle(8, 218, 193, 11, bgColor, true, 1)
emu.drawRectangle(8, 218, 193, 11, fgColor, false, 1)
emu.drawString(11, 220, "Hold left mouse button to switch colors", 0xFFFFFF, bgColor, 1)
--Draw a block behind the mouse cursor - leaves a trail when moving the mouse
emu.drawRectangle(mouseState.x - 2, mouseState.y - 2, 5, 5, 0x3F00FF90, true, 20)
emu.drawRectangle(mouseState.x - 2, mouseState.y - 2, 5, 5, 0x3F000000, false, 20)
end
--Register some code (printInfo function) that will be run at the end of each frame
emu.addEventCallback(printInfo, emu.eventType.endFrame);
--Display a startup message
emu.displayMessage("Script", "Example LUA script loaded.")

View file

@ -340,12 +340,12 @@ namespace FastColoredTextBoxNS
point = AutocompleteParent.PointToClient(offset);
point.Offset(2, tb.CharHeight);
//
bool foundSelected = false;
if (forced || (text.Length >= Menu.MinFragmentLength
&& tb.Selection.IsEmpty /*pops up only if selected range is empty*/
&& (tb.Selection.Start > fragment.Start || text.Length == 0/*pops up only if caret is after first letter*/)))
{
Menu.Fragment = fragment;
bool foundSelected = false;
//build popup menu
foreach (var item in sourceItems)
{
@ -359,31 +359,29 @@ namespace FastColoredTextBoxNS
FocussedItemIndex = visibleItems.Count - 1;
}
}
if (foundSelected)
{
AdjustScroll();
DoSelectedVisible();
}
}
//show popup menu
if (Count > 0)
{
if (!Menu.Visible)
{
CancelEventArgs args = new CancelEventArgs();
Menu.OnOpening(args);
if (!args.Cancel)
{
Menu.Location = point;
Menu.Parent = AutocompleteParent;
Menu.Show();
Menu.BringToFront();
}
}
else
Invalidate();
CancelEventArgs args = new CancelEventArgs();
Menu.OnOpening(args);
if (!args.Cancel)
{
Menu.Location = point;
Menu.Parent = AutocompleteParent;
if (foundSelected)
{
AdjustScroll();
DoSelectedVisible();
}
Menu.Show();
Menu.BringToFront();
}
Menu.Invalidate();
Invalidate();
}
else
Menu.Close();
@ -645,6 +643,9 @@ namespace FastColoredTextBoxNS
case Keys.PageUp:
SelectNext(-10);
return true;
case Keys.OemPeriod:
OnSelecting();
return false;
case Keys.Enter:
OnSelecting();
return true;
@ -695,8 +696,8 @@ namespace FastColoredTextBoxNS
toolTip.Hide(window);
return;
}
var location = new Point(Right + 3 + Menu.Left, Menu.Top);
var location = window.PointToClient(Menu.PointToScreen(new Point(Menu.Width + 3, 0)));
if (string.IsNullOrEmpty(text))
{
toolTip.ToolTipTitle = null;

View file

@ -48,6 +48,12 @@
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.panel1 = new System.Windows.Forms.Panel();
this.txtCode = new FastColoredTextBoxNS.FastColoredTextBox();
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuCopy = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCut = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPaste = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.ctrlHexBox = new Be.Windows.Forms.HexBox();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
@ -72,6 +78,7 @@
this.groupBox1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.txtCode)).BeginInit();
this.contextMenu.SuspendLayout();
this.groupBox2.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
@ -326,6 +333,7 @@
this.txtCode.BackBrush = null;
this.txtCode.CharHeight = 14;
this.txtCode.CharWidth = 8;
this.txtCode.ContextMenuStrip = this.contextMenu;
this.txtCode.CurrentLineColor = System.Drawing.Color.Gainsboro;
this.txtCode.Cursor = System.Windows.Forms.Cursors.IBeam;
this.txtCode.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))));
@ -338,9 +346,58 @@
this.txtCode.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255)))));
this.txtCode.Size = new System.Drawing.Size(361, 272);
this.txtCode.TabIndex = 6;
this.txtCode.TabLength = 2;
this.txtCode.Zoom = 100;
this.txtCode.TextChanged += new System.EventHandler<FastColoredTextBoxNS.TextChangedEventArgs>(this.txtCode_TextChanged);
//
// contextMenu
//
this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuCopy,
this.mnuCut,
this.mnuPaste,
this.toolStripMenuItem5,
this.mnuSelectAll});
this.contextMenu.Name = "contextMenu";
this.contextMenu.Size = new System.Drawing.Size(165, 98);
//
// mnuCopy
//
this.mnuCopy.Name = "mnuCopy";
this.mnuCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
this.mnuCopy.Size = new System.Drawing.Size(164, 22);
this.mnuCopy.Text = "Copy";
this.mnuCopy.Click += new System.EventHandler(this.mnuCopy_Click);
//
// mnuCut
//
this.mnuCut.Name = "mnuCut";
this.mnuCut.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
this.mnuCut.Size = new System.Drawing.Size(164, 22);
this.mnuCut.Text = "Cut";
this.mnuCut.Click += new System.EventHandler(this.mnuCut_Click);
//
// mnuPaste
//
this.mnuPaste.Name = "mnuPaste";
this.mnuPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
this.mnuPaste.Size = new System.Drawing.Size(164, 22);
this.mnuPaste.Text = "Paste";
this.mnuPaste.Click += new System.EventHandler(this.mnuPaste_Click);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(161, 6);
//
// mnuSelectAll
//
this.mnuSelectAll.Name = "mnuSelectAll";
this.mnuSelectAll.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
this.mnuSelectAll.Size = new System.Drawing.Size(164, 22);
this.mnuSelectAll.Text = "Select All";
this.mnuSelectAll.Click += new System.EventHandler(this.mnuSelectAll_Click);
//
// groupBox2
//
this.groupBox2.Controls.Add(this.ctrlHexBox);
@ -492,6 +549,7 @@
this.groupBox1.ResumeLayout(false);
this.panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.txtCode)).EndInit();
this.contextMenu.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
@ -534,5 +592,11 @@
private System.Windows.Forms.ToolStripMenuItem mnuIncreaseFontSize;
private System.Windows.Forms.ToolStripMenuItem mnuDecreaseFontSize;
private System.Windows.Forms.ToolStripMenuItem mnuResetFontSize;
private System.Windows.Forms.ContextMenuStrip contextMenu;
private System.Windows.Forms.ToolStripMenuItem mnuCopy;
private System.Windows.Forms.ToolStripMenuItem mnuCut;
private System.Windows.Forms.ToolStripMenuItem mnuPaste;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
private System.Windows.Forms.ToolStripMenuItem mnuSelectAll;
}
}

View file

@ -34,16 +34,11 @@ namespace Mesen.GUI.Debugger
}
mnuEnableSyntaxHighlighting.Checked = ConfigManager.Config.DebugInfo.AssemblerCodeHighlighting;
txtCode.Font = new Font(BaseControl.MonospaceFontFamily, 10);
txtCode.Font = new Font(BaseControl.MonospaceFontFamily, BaseControl.DefaultFontSize);
txtCode.Zoom = ConfigManager.Config.DebugInfo.AssemblerZoom;
UpdateCodeHighlighting();
if(!string.IsNullOrWhiteSpace(code)) {
_isEditMode = true;
_containedRtiRts = ContainsRtiOrRts(code);
}
_startAddress = startAddress;
_blockLength = blockLength;
@ -56,7 +51,18 @@ namespace Mesen.GUI.Debugger
ctrlHexBox.ByteProvider = new StaticByteProvider(new byte[0]);
txtStartAddress.Text = _startAddress.ToString("X4");
txtCode.Text = code;
if(!string.IsNullOrWhiteSpace(code)) {
_isEditMode = true;
_containedRtiRts = ContainsRtiOrRts(code);
txtCode.Text = code;
} else {
code = ";Input 6502 assembly here.\n;The resulting bytecode is\n;displayed on the right.\n; -Labels can be used.\n; -Use .byte to define data\n";
txtCode.Text = code;
txtCode.Selection = txtCode.GetLine(5);
txtCode.SelectionLength = 0;
}
toolTip.SetToolTip(picSizeWarning, "Warning: The new code exceeds the original code's length." + Environment.NewLine + "Applying this modification will overwrite other portions of the code and potentially cause problems.");
toolTip.SetToolTip(picStartAddressWarning, "Warning: Start address is invalid. Must be a valid hexadecimal string.");
@ -330,6 +336,26 @@ namespace Mesen.GUI.Debugger
{
txtCode.RestoreFontSize();
}
private void mnuCopy_Click(object sender, EventArgs e)
{
txtCode.Copy();
}
private void mnuCut_Click(object sender, EventArgs e)
{
txtCode.Cut();
}
private void mnuPaste_Click(object sender, EventArgs e)
{
txtCode.Paste();
}
private void mnuSelectAll_Click(object sender, EventArgs e)
{
txtCode.SelectAll();
}
enum AssemblerSpecialCodes
{

View file

@ -120,6 +120,9 @@
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="contextMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>222, 17</value>
</metadata>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>

View file

@ -55,6 +55,10 @@
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
this.mnuSaveBeforeRun = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoReload = new System.Windows.Forms.ToolStripMenuItem();
this.onStartupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuBlankWindow = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTutorialScript = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoLoadLastScript = new System.Windows.Forms.ToolStripMenuItem();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.btnOpen = new System.Windows.Forms.ToolStripButton();
this.btnSave = new System.Windows.Forms.ToolStripButton();
@ -66,6 +70,8 @@
this.mnuCopy = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCut = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPaste = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuSelectAll = new System.Windows.Forms.ToolStripMenuItem();
this.ctrlSplit = new Mesen.GUI.Controls.ctrlSplitContainer();
this.txtLog = new System.Windows.Forms.TextBox();
this.tmrLog = new System.Windows.Forms.Timer(this.components);
@ -91,7 +97,7 @@
this.scriptToolStripMenuItem});
this.mnuMain.Location = new System.Drawing.Point(0, 0);
this.mnuMain.Name = "mnuMain";
this.mnuMain.Size = new System.Drawing.Size(425, 24);
this.mnuMain.Size = new System.Drawing.Size(965, 24);
this.mnuMain.TabIndex = 0;
this.mnuMain.Text = "menuStrip1";
//
@ -237,7 +243,8 @@
this.mnuStop,
this.toolStripMenuItem3,
this.mnuSaveBeforeRun,
this.mnuAutoReload});
this.mnuAutoReload,
this.onStartupToolStripMenuItem});
this.scriptToolStripMenuItem.Name = "scriptToolStripMenuItem";
this.scriptToolStripMenuItem.Size = new System.Drawing.Size(49, 20);
this.scriptToolStripMenuItem.Text = "Script";
@ -247,7 +254,7 @@
this.mnuRun.Image = global::Mesen.GUI.Properties.Resources.Play;
this.mnuRun.Name = "mnuRun";
this.mnuRun.ShortcutKeys = System.Windows.Forms.Keys.F5;
this.mnuRun.Size = new System.Drawing.Size(236, 22);
this.mnuRun.Size = new System.Drawing.Size(258, 22);
this.mnuRun.Text = "Run";
this.mnuRun.Click += new System.EventHandler(this.mnuRun_Click);
//
@ -256,29 +263,60 @@
this.mnuStop.Image = global::Mesen.GUI.Properties.Resources.Stop;
this.mnuStop.Name = "mnuStop";
this.mnuStop.ShortcutKeyDisplayString = "Esc";
this.mnuStop.Size = new System.Drawing.Size(236, 22);
this.mnuStop.Size = new System.Drawing.Size(258, 22);
this.mnuStop.Text = "Stop";
this.mnuStop.Click += new System.EventHandler(this.mnuStop_Click);
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(233, 6);
this.toolStripMenuItem3.Size = new System.Drawing.Size(255, 6);
//
// mnuSaveBeforeRun
//
this.mnuSaveBeforeRun.CheckOnClick = true;
this.mnuSaveBeforeRun.Name = "mnuSaveBeforeRun";
this.mnuSaveBeforeRun.Size = new System.Drawing.Size(236, 22);
this.mnuSaveBeforeRun.Size = new System.Drawing.Size(258, 22);
this.mnuSaveBeforeRun.Text = "Auto-save before running";
//
// mnuAutoReload
//
this.mnuAutoReload.CheckOnClick = true;
this.mnuAutoReload.Name = "mnuAutoReload";
this.mnuAutoReload.Size = new System.Drawing.Size(236, 22);
this.mnuAutoReload.Size = new System.Drawing.Size(258, 22);
this.mnuAutoReload.Text = "Auto-reload when file changes";
//
// onStartupToolStripMenuItem
//
this.onStartupToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuBlankWindow,
this.mnuTutorialScript,
this.mnuAutoLoadLastScript});
this.onStartupToolStripMenuItem.Name = "onStartupToolStripMenuItem";
this.onStartupToolStripMenuItem.Size = new System.Drawing.Size(258, 22);
this.onStartupToolStripMenuItem.Text = "When opening the script window...";
//
// mnuBlankWindow
//
this.mnuBlankWindow.Name = "mnuBlankWindow";
this.mnuBlankWindow.Size = new System.Drawing.Size(227, 22);
this.mnuBlankWindow.Text = "Display a blank code window";
this.mnuBlankWindow.Click += new System.EventHandler(this.mnuBlankWindow_Click);
//
// mnuTutorialScript
//
this.mnuTutorialScript.Name = "mnuTutorialScript";
this.mnuTutorialScript.Size = new System.Drawing.Size(227, 22);
this.mnuTutorialScript.Text = "Display the tutorial script";
this.mnuTutorialScript.Click += new System.EventHandler(this.mnuTutorialScript_Click);
//
// mnuAutoLoadLastScript
//
this.mnuAutoLoadLastScript.Name = "mnuAutoLoadLastScript";
this.mnuAutoLoadLastScript.Size = new System.Drawing.Size(227, 22);
this.mnuAutoLoadLastScript.Text = "Load the last script loaded";
this.mnuAutoLoadLastScript.Click += new System.EventHandler(this.mnuAutoLoadLastScript_Click);
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
@ -290,7 +328,7 @@
this.toolStrip1.Location = new System.Drawing.Point(0, 24);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
this.toolStrip1.Size = new System.Drawing.Size(425, 25);
this.toolStrip1.Size = new System.Drawing.Size(965, 25);
this.toolStrip1.TabIndex = 1;
this.toolStrip1.Text = "toolStrip1";
//
@ -378,7 +416,7 @@
this.txtScriptContent.RightBracket = ')';
this.txtScriptContent.RightBracket2 = '}';
this.txtScriptContent.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255)))));
this.txtScriptContent.Size = new System.Drawing.Size(425, 240);
this.txtScriptContent.Size = new System.Drawing.Size(965, 421);
this.txtScriptContent.TabIndex = 3;
this.txtScriptContent.TabLength = 2;
this.txtScriptContent.Zoom = 100;
@ -388,15 +426,17 @@
this.contextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuCopy,
this.mnuCut,
this.mnuPaste});
this.mnuPaste,
this.toolStripMenuItem5,
this.mnuSelectAll});
this.contextMenu.Name = "contextMenu";
this.contextMenu.Size = new System.Drawing.Size(145, 70);
this.contextMenu.Size = new System.Drawing.Size(165, 98);
//
// mnuCopy
//
this.mnuCopy.Name = "mnuCopy";
this.mnuCopy.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
this.mnuCopy.Size = new System.Drawing.Size(144, 22);
this.mnuCopy.Size = new System.Drawing.Size(164, 22);
this.mnuCopy.Text = "Copy";
this.mnuCopy.Click += new System.EventHandler(this.mnuCopy_Click);
//
@ -404,7 +444,7 @@
//
this.mnuCut.Name = "mnuCut";
this.mnuCut.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
this.mnuCut.Size = new System.Drawing.Size(144, 22);
this.mnuCut.Size = new System.Drawing.Size(164, 22);
this.mnuCut.Text = "Cut";
this.mnuCut.Click += new System.EventHandler(this.mnuCut_Click);
//
@ -412,10 +452,23 @@
//
this.mnuPaste.Name = "mnuPaste";
this.mnuPaste.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
this.mnuPaste.Size = new System.Drawing.Size(144, 22);
this.mnuPaste.Size = new System.Drawing.Size(164, 22);
this.mnuPaste.Text = "Paste";
this.mnuPaste.Click += new System.EventHandler(this.mnuPaste_Click);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(161, 6);
//
// mnuSelectAll
//
this.mnuSelectAll.Name = "mnuSelectAll";
this.mnuSelectAll.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
this.mnuSelectAll.Size = new System.Drawing.Size(164, 22);
this.mnuSelectAll.Text = "Select All";
this.mnuSelectAll.Click += new System.EventHandler(this.mnuSelectAll_Click);
//
// ctrlSplit
//
this.ctrlSplit.Dock = System.Windows.Forms.DockStyle.Fill;
@ -434,8 +487,8 @@
//
this.ctrlSplit.Panel2.Controls.Add(this.txtLog);
this.ctrlSplit.Panel2.Padding = new System.Windows.Forms.Padding(0, 2, 0, 0);
this.ctrlSplit.Size = new System.Drawing.Size(425, 335);
this.ctrlSplit.SplitterDistance = 242;
this.ctrlSplit.Size = new System.Drawing.Size(965, 516);
this.ctrlSplit.SplitterDistance = 423;
this.ctrlSplit.TabIndex = 4;
//
// txtLog
@ -447,7 +500,7 @@
this.txtLog.Name = "txtLog";
this.txtLog.ReadOnly = true;
this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.txtLog.Size = new System.Drawing.Size(425, 87);
this.txtLog.Size = new System.Drawing.Size(965, 87);
this.txtLog.TabIndex = 0;
//
// tmrLog
@ -461,16 +514,16 @@
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1,
this.lblScriptActive});
this.statusStrip1.Location = new System.Drawing.Point(0, 384);
this.statusStrip1.Location = new System.Drawing.Point(0, 565);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(425, 22);
this.statusStrip1.Size = new System.Drawing.Size(965, 22);
this.statusStrip1.TabIndex = 6;
this.statusStrip1.Text = "statusStrip1";
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(410, 17);
this.toolStripStatusLabel1.Size = new System.Drawing.Size(950, 17);
this.toolStripStatusLabel1.Spring = true;
//
// lblScriptActive
@ -486,7 +539,7 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(425, 406);
this.ClientSize = new System.Drawing.Size(965, 587);
this.Controls.Add(this.ctrlSplit);
this.Controls.Add(this.toolStrip1);
this.Controls.Add(this.mnuMain);
@ -555,5 +608,11 @@
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem4;
private System.Windows.Forms.ToolStripMenuItem mnuNewScript;
private System.Windows.Forms.ToolStripMenuItem mnuSaveAs;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem5;
private System.Windows.Forms.ToolStripMenuItem mnuSelectAll;
private System.Windows.Forms.ToolStripMenuItem onStartupToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem mnuBlankWindow;
private System.Windows.Forms.ToolStripMenuItem mnuTutorialScript;
private System.Windows.Forms.ToolStripMenuItem mnuAutoLoadLastScript;
}
}

View file

@ -5,6 +5,7 @@ using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@ -25,7 +26,7 @@ namespace Mesen.GUI.Debugger
private AutocompleteMenu _popupMenu;
private string _originalText = "";
public frmScript()
public frmScript(bool forceBlank = false)
{
InitializeComponent();
@ -65,12 +66,32 @@ namespace Mesen.GUI.Debugger
_popupMenu.Items.SetAutocompleteItems(items);
UpdateRecentScripts();
mnuTutorialScript.Checked = ConfigManager.Config.DebugInfo.ScriptStartupBehavior == ScriptStartupBehavior.ShowTutorial;
mnuBlankWindow.Checked = ConfigManager.Config.DebugInfo.ScriptStartupBehavior == ScriptStartupBehavior.ShowBlankWindow;
mnuAutoLoadLastScript.Checked = ConfigManager.Config.DebugInfo.ScriptStartupBehavior == ScriptStartupBehavior.LoadLastScript;
if(!forceBlank) {
if(mnuAutoLoadLastScript.Checked && mnuRecentScripts.DropDownItems.Count > 0) {
string scriptToLoad = ConfigManager.Config.DebugInfo.RecentScripts.Where((s) => File.Exists(s)).FirstOrDefault();
if(scriptToLoad != null) {
LoadScriptFile(scriptToLoad, false);
}
} else if(mnuTutorialScript.Checked) {
using(Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Mesen.GUI.Debugger.Example.lua")) {
using(StreamReader reader = new StreamReader(stream)) {
txtScriptContent.Text = reader.ReadToEnd();
_originalText = txtScriptContent.Text;
}
}
}
}
if(!ConfigManager.Config.DebugInfo.ScriptWindowSize.IsEmpty) {
this.Size = ConfigManager.Config.DebugInfo.ScriptWindowSize;
}
mnuSaveBeforeRun.Checked = ConfigManager.Config.DebugInfo.SaveScriptBeforeRun;
mnuAutoReload.Checked = ConfigManager.Config.DebugInfo.AutoReloadScript;
if(ConfigManager.Config.DebugInfo.ScriptCodeWindowHeight >= ctrlSplit.Panel1MinSize) {
if(ConfigManager.Config.DebugInfo.ScriptCodeWindowHeight == Int32.MaxValue) {
ctrlSplit.CollapsePanel();
@ -78,7 +99,7 @@ namespace Mesen.GUI.Debugger
ctrlSplit.SplitterDistance = ConfigManager.Config.DebugInfo.ScriptCodeWindowHeight;
}
}
txtScriptContent.Font = new Font(BaseControl.MonospaceFontFamily, 10);
txtScriptContent.Font = new Font(BaseControl.MonospaceFontFamily, BaseControl.DefaultFontSize);
txtScriptContent.Zoom = ConfigManager.Config.DebugInfo.ScriptZoom;
if(!this.DesignMode) {
@ -97,22 +118,26 @@ namespace Mesen.GUI.Debugger
protected override void OnClosing(CancelEventArgs e)
{
if(_originalText != txtScriptContent.Text) {
DialogResult result = MessageBox.Show("You have unsaved changes for this script - would you like to save them?", "Script Window", MessageBoxButtons.YesNoCancel);
if((result == DialogResult.Yes && !SaveScript()) || result == DialogResult.Cancel) {
e.Cancel = true;
return;
}
if(!SavePrompt()) {
e.Cancel = true;
return;
}
if(_scriptId >= 0) {
InteropEmu.DebugRemoveScript(_scriptId);
}
ConfigManager.Config.DebugInfo.ScriptWindowSize = this.WindowState == FormWindowState.Maximized ? this.RestoreBounds.Size : this.Size;
ConfigManager.Config.DebugInfo.SaveScriptBeforeRun = mnuSaveBeforeRun.Checked;
ConfigManager.Config.DebugInfo.AutoReloadScript = mnuAutoReload.Checked;
if(mnuAutoLoadLastScript.Checked) {
ConfigManager.Config.DebugInfo.ScriptStartupBehavior = ScriptStartupBehavior.LoadLastScript;
} else if(mnuTutorialScript.Checked) {
ConfigManager.Config.DebugInfo.ScriptStartupBehavior = ScriptStartupBehavior.ShowTutorial;
} else {
ConfigManager.Config.DebugInfo.ScriptStartupBehavior = ScriptStartupBehavior.ShowBlankWindow;
}
ConfigManager.Config.DebugInfo.ScriptCodeWindowHeight = ctrlSplit.Panel2.Height <= 2 ? Int32.MaxValue : ctrlSplit.SplitterDistance;
ConfigManager.Config.DebugInfo.ScriptZoom = txtScriptContent.Zoom;
ConfigManager.Config.DebugInfo.AutoLoadLastScript = mnuAutoLoadLastScript.Checked;
ConfigManager.ApplyChanges();
base.OnClosing(e);
@ -122,7 +147,6 @@ namespace Mesen.GUI.Debugger
{
if(keyData == Keys.Escape) {
StopScript();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
@ -137,16 +161,32 @@ namespace Mesen.GUI.Debugger
}
}
private void LoadScriptFile(string filepath)
private bool SavePrompt()
{
if(_originalText != txtScriptContent.Text) {
DialogResult result = MessageBox.Show("You have unsaved changes for this script - would you like to save them?", "Script Window", MessageBoxButtons.YesNoCancel);
if((result == DialogResult.Yes && !SaveScript()) || result == DialogResult.Cancel) {
return false;
}
}
return true;
}
private void LoadScriptFile(string filepath, bool runScript = true)
{
if(File.Exists(filepath)) {
if(!SavePrompt()) {
return;
}
string content = File.ReadAllText(filepath);
SetFilePath(filepath);
txtScriptContent.Text = content;
txtScriptContent.ClearUndo();
ConfigManager.Config.DebugInfo.AddRecentScript(filepath);
UpdateRecentScripts();
RunScript();
if(runScript) {
RunScript();
}
_originalText = txtScriptContent.Text;
_lastTimestamp = File.GetLastWriteTime(filepath);
@ -157,12 +197,14 @@ namespace Mesen.GUI.Debugger
{
mnuRecentScripts.DropDownItems.Clear();
foreach(string recentScript in ConfigManager.Config.DebugInfo.RecentScripts) {
ToolStripMenuItem tsmi = new ToolStripMenuItem();
tsmi.Text = Path.GetFileName(recentScript);
tsmi.Click += (object sender, EventArgs args) => {
LoadScriptFile(recentScript);
};
mnuRecentScripts.DropDownItems.Add(tsmi);
if(File.Exists(recentScript)) {
ToolStripMenuItem tsmi = new ToolStripMenuItem();
tsmi.Text = Path.GetFileName(recentScript);
tsmi.Click += (object sender, EventArgs args) => {
LoadScriptFile(recentScript);
};
mnuRecentScripts.DropDownItems.Add(tsmi);
}
}
mnuRecentScripts.Enabled = mnuRecentScripts.DropDownItems.Count > 0;
@ -321,6 +363,11 @@ namespace Mesen.GUI.Debugger
{
txtScriptContent.Paste();
}
private void mnuSelectAll_Click(object sender, EventArgs e)
{
txtScriptContent.SelectAll();
}
private void mnuIncreaseFontSize_Click(object sender, EventArgs e)
{
@ -339,7 +386,28 @@ namespace Mesen.GUI.Debugger
private void mnuNewScript_Click(object sender, EventArgs e)
{
DebugWindowManager.OpenDebugWindow(DebugWindow.ScriptWindow);
DebugWindowManager.OpenScriptWindow(true);
}
private void mnuAutoLoadLastScript_Click(object sender, EventArgs e)
{
mnuAutoLoadLastScript.Checked = true;
mnuTutorialScript.Checked = false;
mnuBlankWindow.Checked = false;
}
private void mnuTutorialScript_Click(object sender, EventArgs e)
{
mnuAutoLoadLastScript.Checked = false;
mnuTutorialScript.Checked = true;
mnuBlankWindow.Checked = false;
}
private void mnuBlankWindow_Click(object sender, EventArgs e)
{
mnuAutoLoadLastScript.Checked = false;
mnuTutorialScript.Checked = false;
mnuBlankWindow.Checked = true;
}
static readonly List<List<string>> _availableFunctions = new List<List<string>>() {
@ -380,10 +448,34 @@ namespace Mesen.GUI.Debugger
new List<string> {"func","emu.addCheat","emu.addCheat(cheatCode)","cheatCode - *String* A game genie format cheat code.","","Activates a game genie cheat code (6 or 8 characters).\nNote: cheat codes added via this function are not permanent and not visible in the UI."},
new List<string> {"func","emu.clearCheats","emu.clearCheats()","","","Removes all active cheat codes (has no impact on cheat codes saved within the UI)"},
new List<string> {"func","emu.takeScreenshot","emu.takeScreenshot()","","*String* A binary string containing a PNG image.","Takes a screenshot and returns a PNG file as a string.\nThe screenshot is not saved to the disk."},
new List<string> {"enum","emu.eventType","emu.eventType.[value]","","","Values:\npower = 0,\nreset = 1,\nnmi = 2,\nirq = 3,\nstartFrame = 4,\nendFrame = 5,\ncodeBreak = 6\n\nUsed by addEventCallback / removeEventCallback calls."},
new List<string> {"enum","emu.eventType","emu.eventType.[value]","","","Values:\nreset = 0,\nnmi = 1,\nirq = 2,\nstartFrame = 3,\nendFrame = 4,\ncodeBreak = 5\n\nUsed by addEventCallback / removeEventCallback calls."},
new List<string> {"enum","emu.eventType.reset","Triggered when a soft reset occurs","","",""},
new List<string> {"enum","emu.eventType.nmi","Triggered when an nmi occurs","","",""},
new List<string> {"enum","emu.eventType.irq","Triggered when an irq occurs","","",""},
new List<string> {"enum","emu.eventType.startFrame","Triggered at the start of a frame (cycle 0, scanline -1)","","",""},
new List<string> {"enum","emu.eventType.endFrame","Triggered at the end of a frame (cycle 0, scanline 241)","","",""},
new List<string> {"enum","emu.eventType.codeBreak","Triggered when code execution breaks (e.g due to a breakpoint, etc.)","","",""},
new List<string> {"enum","emu.executeCountType","emu.executeCountType.[value]","","","Values:\ncpuCycles = 0,\nppuCycles = 1,\ncpuInstructions = 2\n\nUsed by execute calls." },
new List<string> {"enum","emu.executeCountType.cpuCycles","Count the number of CPU cycles","","",""},
new List<string> {"enum","emu.executeCountType.ppuCycles","Count the number of PPU cycles","","",""},
new List<string> {"enum","emu.executeCountType.cpuInstructions","Count the number of CPU instructions","","",""},
new List<string> {"enum","emu.memCallbackType","emu.memCallbackType.[value]","","","Values:\ncpuRead = 0,\ncpuWrite = 1,\ncpuExec = 2,\nppuRead = 3,\nppuWrite = 4\n\nUsed by addMemoryCallback / removeMemoryCallback calls."},
new List<string> {"enum","emu.memCallbackType.cpuRead","Triggered when a read instruction is executed","","",""},
new List<string> {"enum","emu.memCallbackType.cpuWrite","Triggered when a write instruction is executed","","",""},
new List<string> {"enum","emu.memCallbackType.cpuExec","Triggered when any memory read occurs due to the CPU's code execution","","",""},
new List<string> {"enum","emu.memCallbackType.ppuRead","Triggered when the PPU reads from its memory bus","","",""},
new List<string> {"enum","emu.memCallbackType.ppuWrite","Triggered when the PPU writes to its memory bus","","",""},
new List<string> {"enum","emu.memType","emu.memType.[value]", "","","Values:\ncpu = 0,\nppu = 1,\npalette = 2,\noam = 3,\nsecondaryOam = 4,\nprgRom = 5,\nchrRom = 6,\nchrRam = 7,\nworkRam = 8,\nsaveRam = 9\n\nUsed by read / write calls."},
new List<string> {"enum","emu.memType.cpu","CPU memory - $0000 to $FFFF","","",""},
new List<string> {"enum","emu.memType.ppu","PPU memory - $0000 to $3FFF","","",""},
new List<string> {"enum","emu.memType.palette","Palette memory - $00 to $3F","","",""},
new List<string> {"enum","emu.memType.oam","OAM memory - $00 to $FF","","",""},
new List<string> {"enum","emu.memType.secondaryOam","$00 to $1F","","",""},
new List<string> {"enum","emu.memType.prgRom","PRG ROM - Range varies by game","","",""},
new List<string> {"enum","emu.memType.chrRom","CHR ROM - Range varies by game","","",""},
new List<string> {"enum","emu.memType.chrRam","CHR RAM - Range varies by game","","",""},
new List<string> {"enum","emu.memType.workRam","Work RAM - Range varies by game","","",""},
new List<string> {"enum","emu.memType.saveRam","Save RAM - Range varies by game","","",""},
};
}

View file

@ -840,6 +840,7 @@
<Compile Include="ResourceManager.cs" />
<Compile Include="RuntimeChecker.cs" />
<Compile Include="SingleInstance.cs" />
<EmbeddedResource Include="Debugger\Example.lua" />
<None Include="Resources\PipetteSmall.png" />
<None Include="Resources\Enum.png" />
<None Include="Resources\Script.png" />