Started preliminary work for the Visual Debugger
This commit is contained in:
parent
4fcd89effd
commit
5d47b73298
11 changed files with 840 additions and 18 deletions
|
|
@ -53,6 +53,7 @@ list(APPEND DEBUGGER_SOURCE_FILES
|
|||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/debugger_main.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/Debugger.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DebuggerNew.cpp
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
|
||||
|
|
@ -186,7 +187,7 @@ target_link_libraries(${RUNTIME_TARGET} SDL2main SDL2 SDL2_image)
|
|||
target_link_libraries(${DEBUGGER_TARGET} SDL2main SDL2 SDL2_image)
|
||||
|
||||
target_link_libraries(${RUNTIME_TARGET} ostd)
|
||||
target_link_libraries(${DEBUGGER_TARGET} ostd)
|
||||
target_link_libraries(${DEBUGGER_TARGET} ostd ogfx)
|
||||
target_link_libraries(${ASSEMBLER_TARGET} ostd)
|
||||
target_link_libraries(${TOOLS_TARGET} ostd)
|
||||
#-----------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
## --
|
||||
## -- This file is automatically generated by the DragonAssembler (version 0.4.1635)
|
||||
## -- This file is automatically generated by the DragonAssembler (version 0.4.1637)
|
||||
## -- Please do not modify this file in any way.
|
||||
## --
|
||||
|
||||
|
|
|
|||
BIN
extra/res/Courier Prime.ttf
Normal file
BIN
extra/res/Courier Prime.ttf
Normal file
Binary file not shown.
BIN
extra/res/UbuntuMono-R.ttf
Normal file
BIN
extra/res/UbuntuMono-R.ttf
Normal file
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
1636
|
||||
1638
|
||||
|
|
|
|||
561
src/debugger/DebuggerNew.cpp
Normal file
561
src/debugger/DebuggerNew.cpp
Normal file
|
|
@ -0,0 +1,561 @@
|
|||
#include "DebuggerNew.hpp"
|
||||
#include <SDL2/SDL_keycode.h>
|
||||
#include <cstdint>
|
||||
#include <ogfx/BasicRenderer.hpp>
|
||||
#include <ogfx/WindowBase.hpp>
|
||||
#include <ostd/Defines.hpp>
|
||||
#include <ostd/Geometry.hpp>
|
||||
#include <ostd/IOHandlers.hpp>
|
||||
#include <ostd/Random.hpp>
|
||||
#include <ostd/String.hpp>
|
||||
#include "DisassemblyLoader.hpp"
|
||||
#include "../runtime/DragonRuntime.hpp"
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
Button::EventListener::EventListener(Button& _parent) : parent(_parent)
|
||||
{
|
||||
connectSignal(ostd::tBuiltinSignals::KeyPressed);
|
||||
connectSignal(ostd::tBuiltinSignals::KeyReleased);
|
||||
connectSignal(ostd::tBuiltinSignals::MouseMoved);
|
||||
connectSignal(ostd::tBuiltinSignals::MousePressed);
|
||||
connectSignal(ostd::tBuiltinSignals::MouseReleased);
|
||||
connectSignal(ostd::tBuiltinSignals::OnGuiEvent);
|
||||
connectSignal(ostd::tBuiltinSignals::WindowResized);
|
||||
}
|
||||
|
||||
void Button::EventListener::handleSignal(ostd::tSignal& signal)
|
||||
{
|
||||
if (signal.ID == ostd::tBuiltinSignals::KeyPressed)
|
||||
{
|
||||
if (m_lastEvent != eEventType::KeyPressed)
|
||||
{
|
||||
m_lastEvent = eEventType::KeyPressed;
|
||||
}
|
||||
auto& data = (ogfx::KeyEventData&)signal.userData;
|
||||
if (data.keyCode == SDLK_BACKSPACE)
|
||||
{
|
||||
}
|
||||
else if (data.keyCode == SDLK_LEFT)
|
||||
{
|
||||
}
|
||||
else if (data.keyCode == SDLK_RIGHT)
|
||||
{
|
||||
}
|
||||
else if (data.keyCode == SDLK_RETURN)
|
||||
{
|
||||
}
|
||||
else if (data.keyCode == SDLK_TAB)
|
||||
{
|
||||
}
|
||||
}
|
||||
else if (signal.ID == ostd::tBuiltinSignals::MouseMoved)
|
||||
{
|
||||
auto& data = (ogfx::MouseEventData&)signal.userData;
|
||||
if (parent.contains((float)data.position_x, (float)data.position_y))
|
||||
parent.m_mouseInside = true;
|
||||
else
|
||||
parent.m_mouseInside = false;
|
||||
}
|
||||
else if (signal.ID == ostd::tBuiltinSignals::MousePressed)
|
||||
{
|
||||
auto& data = (ogfx::MouseEventData&)signal.userData;
|
||||
if (data.button == ogfx::MouseEventData::eButton::Left && parent.m_gfx != nullptr && parent.m_mouseInside)
|
||||
{
|
||||
ostd::String text = parent.m_text;
|
||||
ostd::Vec2 relativePosition = { (float)data.position_x, (float)data.position_y };
|
||||
relativePosition -= (parent.getPosition());
|
||||
parent.m_pressed = true;
|
||||
}
|
||||
}
|
||||
else if (signal.ID == ostd::tBuiltinSignals::MouseReleased)
|
||||
{
|
||||
auto& data = (ogfx::MouseEventData&)signal.userData;
|
||||
if (data.button == ogfx::MouseEventData::eButton::Left && parent.m_gfx != nullptr)
|
||||
{
|
||||
if (parent.m_pressed)
|
||||
{
|
||||
ActionEventData aed(parent, parent.getName(), eActionEventType::Pressed, ostd::BaseObject::InvalidRef());
|
||||
ostd::SignalHandler::emitSignal(Button::actionEventSignalID, ostd::tSignalPriority::RealTime, aed);
|
||||
}
|
||||
parent.m_pressed = false;
|
||||
}
|
||||
}
|
||||
onSignalHandled(signal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Button& Button::create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name)
|
||||
{
|
||||
setPosition(position);
|
||||
setSize(size);
|
||||
m_name = name;
|
||||
m_eventListener = new EventListener(*this); //TODO: Delete -- Memory Leak
|
||||
m_theme = tDefaultThemes::DefaultTheme;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Button::render(ogfx::BasicRenderer2D& gfx)
|
||||
{
|
||||
m_gfx = &gfx;
|
||||
ostd::Color backgroundColor = m_theme.backgroundColor;
|
||||
ostd::Color borderColor = m_theme.borderColor;
|
||||
ostd::Color textColor = m_theme.textColor;
|
||||
if (m_pressed)
|
||||
{
|
||||
backgroundColor = m_theme.backgroundColor_Pressed;
|
||||
borderColor = m_theme.borderColor_Pressed;
|
||||
textColor = m_theme.textColor_Pressed;
|
||||
}
|
||||
else if (m_mouseInside)
|
||||
{
|
||||
backgroundColor = m_theme.backgroundColor_Hover;
|
||||
borderColor = m_theme.borderColor_Hover;
|
||||
textColor = m_theme.textColor_Hover;
|
||||
}
|
||||
gfx.outlinedRect(*this, backgroundColor, borderColor, 2);
|
||||
if (m_text.len() > 0)
|
||||
{
|
||||
ostd::IPoint strSize = gfx.getStringSize(m_text, m_theme.fontSize);
|
||||
ostd::Vec2 txtPos = getPosition() + ostd::Vec2 { (getw() / 2.0f) - (strSize.x / 2.0f), (geth() / 2.0f) - (strSize.y / 2.0f) };
|
||||
gfx.drawString(m_text, txtPos, textColor, m_theme.fontSize);
|
||||
}
|
||||
onRender(gfx);
|
||||
}
|
||||
|
||||
void Button::update(void)
|
||||
{
|
||||
onUpdate();
|
||||
}
|
||||
|
||||
void Button::fixedUpdate(void)
|
||||
{
|
||||
onFixedUpdate();
|
||||
}
|
||||
|
||||
void Button::setText(const ostd::String& text)
|
||||
{
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
void Button::appendText(const ostd::String& text)
|
||||
{
|
||||
m_text.add(text);
|
||||
}
|
||||
|
||||
void Button::setTheme(Theme theme)
|
||||
{
|
||||
m_theme = theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
//DebuggerNew::Utils
|
||||
DisassemblyList DebuggerNew::findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin)
|
||||
{
|
||||
if (code.size() <= (codeRegionMargin * 2) + 1) return code;
|
||||
std::vector<dragon::code::Assembler::tDisassemblyLine> codeRegion;
|
||||
uint16_t start = 0;
|
||||
uint16_t end = (codeRegionMargin * 2);
|
||||
for (int32_t i = 0; i < code.size(); i++)
|
||||
{
|
||||
if (code[i].addr != address) continue;
|
||||
if (i + 1 <= codeRegionMargin) break;
|
||||
if (code.size() - (i + 1) < codeRegionMargin)
|
||||
{
|
||||
end = code.size() - 1;
|
||||
start = end - ((codeRegionMargin * 2) + 1);
|
||||
break;
|
||||
}
|
||||
start = i - codeRegionMargin;
|
||||
end = i + codeRegionMargin;
|
||||
break;
|
||||
}
|
||||
for (int16_t i = start; i <= end; i++)
|
||||
codeRegion.push_back(code[i]);
|
||||
return codeRegion;
|
||||
}
|
||||
|
||||
ostd::String DebuggerNew::findSymbol(const DisassemblyList& list, uint16_t address, uint16_t* outSize)
|
||||
{
|
||||
for (auto& line : list)
|
||||
{
|
||||
if (line.addr == address)
|
||||
{
|
||||
if (outSize != nullptr)
|
||||
*outSize = line.size;
|
||||
return line.code;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
uint16_t DebuggerNew::findSymbol(const DisassemblyList& list, const ostd::String& symbol, uint16_t* outSize)
|
||||
{
|
||||
for (auto& line : list)
|
||||
{
|
||||
if (line.code == symbol)
|
||||
{
|
||||
if (outSize != nullptr)
|
||||
*outSize = line.size;
|
||||
return line.addr;
|
||||
}
|
||||
}
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
bool DebuggerNew::isValidLabelNameChar(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_');
|
||||
}
|
||||
|
||||
void DebuggerNew::removeBreakPoint(uint16_t addr)
|
||||
{
|
||||
if (debugger.manualBreakPoints.size() == 0)
|
||||
return;
|
||||
int32_t i = 0;
|
||||
for ( ; i < debugger.manualBreakPoints.size(); i++)
|
||||
{
|
||||
if (debugger.manualBreakPoints[i] == addr)
|
||||
break;
|
||||
}
|
||||
if (i >= debugger.manualBreakPoints.size())
|
||||
return;
|
||||
debugger.manualBreakPoints.erase(debugger.manualBreakPoints.begin() + i);
|
||||
}
|
||||
|
||||
bool DebuggerNew::isBreakPoint(uint16_t addr)
|
||||
{
|
||||
for (const auto& b : debugger.manualBreakPoints)
|
||||
if (b == addr) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebuggerNew::addBreakPoint(uint16_t addr)
|
||||
{
|
||||
debugger.manualBreakPoints.push_back(addr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Debugger
|
||||
void DebuggerNew::processErrors(void)
|
||||
{
|
||||
if (!dragon::DragonRuntime::hasError()) return;
|
||||
while (dragon::data::ErrorHandler::hasError())
|
||||
{
|
||||
auto err = dragon::data::ErrorHandler::popError();
|
||||
out.nl().fg(ostd::ConsoleColors::Red).p("Error ").p(ostd::Utils::getHexStr(err.code, true, 8).cpp_str()).p(": ").p(err.text.cpp_str()).nl();
|
||||
}
|
||||
debugger.args.step_exec = true;
|
||||
}
|
||||
|
||||
int32_t DebuggerNew::loadArguments(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
out.fg(ostd::ConsoleColors::Red).p("Error: too few arguments.").nl();
|
||||
out.fg(ostd::ConsoleColors::Red).p("Use the --help option for more info.").reset().nl();
|
||||
return DragonRuntime::RETURN_VAL_TOO_FEW_ARGUMENTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugger.args.machine_config_path = argv[1];
|
||||
if (debugger.args.machine_config_path == "--help")
|
||||
{
|
||||
// print_application_help();
|
||||
return DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER;
|
||||
}
|
||||
for (int32_t i = 2; i < argc; i++)
|
||||
{
|
||||
ostd::String edit(argv[i]);
|
||||
if (edit == "--verbose-load")
|
||||
debugger.args.verbose_load = true;
|
||||
else if (edit == "--step-exec")
|
||||
debugger.args.step_exec = true;
|
||||
else if (edit == "--track-step-diff-off")
|
||||
debugger.args.track_step_diff = false;
|
||||
else if (edit == "--auto-track-data-off")
|
||||
debugger.args.auto_track_all_data_symbols = false;
|
||||
else if (edit == "--hide-vdisplay")
|
||||
debugger.args.hide_virtual_display = true;
|
||||
else if (edit == "--auto-start")
|
||||
debugger.args.auto_start_debug = true;
|
||||
else if (edit == "--force-load")
|
||||
{
|
||||
if ((argc - 1) - i < 2)
|
||||
return DragonRuntime::RETURN_VAL_MISSING_PARAM;
|
||||
i++;
|
||||
debugger.args.force_load_file = argv[i];
|
||||
i++;
|
||||
edit = argv[i];
|
||||
if (!edit.isNumeric())
|
||||
return DragonRuntime::RETURN_VAL_PARAMETER_NOT_NUMERIC;
|
||||
debugger.args.force_load_mem_offset = (uint16_t)edit.toInt();
|
||||
debugger.args.force_load = true;
|
||||
}
|
||||
else if (edit == "--help")
|
||||
{
|
||||
// print_application_help();
|
||||
return DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DragonRuntime::RETURN_VAL_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t DebuggerNew::initRuntime(void)
|
||||
{
|
||||
int32_t init_state = dragon::DragonRuntime::initMachine(debugger.args.machine_config_path,
|
||||
debugger.args.verbose_load,
|
||||
debugger.args.track_step_diff,
|
||||
debugger.args.hide_virtual_display,
|
||||
debugger.args.track_call_stack,
|
||||
true); //CPU Debug Mode Enabled
|
||||
// closeEventListener.init();
|
||||
if (init_state != 0) return init_state; //TODO: Error
|
||||
|
||||
if (debugger.args.force_load)
|
||||
dragon::DragonRuntime::forceLoad(debugger.args.force_load_file, debugger.args.force_load_mem_offset);
|
||||
|
||||
dragon::DisassemblyLoader::loadDirectory(debugger.disassemblyDirectory);
|
||||
debugger.code = dragon::DisassemblyLoader::getCodeTable();
|
||||
debugger.labels = dragon::DisassemblyLoader::getLabelTable();
|
||||
debugger.data = dragon::DisassemblyLoader::getDataTable();
|
||||
|
||||
return DragonRuntime::RETURN_VAL_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Display
|
||||
void DebuggerNew::colorizeInstructionBody(const ostd::String& instBody, bool currentLine, const DisassemblyList& labelList)
|
||||
{
|
||||
ostd::RegexRichString rgxrstr(instBody);
|
||||
rgxrstr.fg("\\{|\\}|\\+|\\*|\\-|\\/|\\(|\\)|\\[|\\]", "Red"); //Operators
|
||||
rgxrstr.fg("0x[0-9A-Fa-f]+|0b[0-1]+|(?<!\\w)[0-9]+(?!\\w)", "Blue"); //Number Constants
|
||||
rgxrstr.fg("(?<!\\w)(r[1-9]|r10|fl|pp|rv|fp|sp|ip|acc)(?!\\w)", "BrightGreen", true); //Registers
|
||||
rgxrstr.fg("\\%low", "Magenta");
|
||||
rgxrstr.col("\\$\\w+", "Cyan", "Black"); //Labels
|
||||
ostd::String instEdit = rgxrstr.getRawString();
|
||||
for (auto& label : labelList)
|
||||
{
|
||||
int32_t index = -1;
|
||||
ostd::String labelEdit = label.code;
|
||||
labelEdit.trim();
|
||||
while ((index = instEdit.indexOf(labelEdit, index + 1)) != -1)
|
||||
{
|
||||
if (index + labelEdit.len() < instEdit.len() && isValidLabelNameChar(instEdit.at(index + labelEdit.len())))
|
||||
continue;
|
||||
ostd::String instStr = instEdit;
|
||||
instStr.cpp_str_ref().replace(index, labelEdit.len(), labelEdit.cpp_str() + "[@@ style foreground:brightgray](" + ostd::Utils::getHexStr(label.addr, true, 2).cpp_str() + ")[@@/]");
|
||||
instEdit = instStr;
|
||||
}
|
||||
}
|
||||
rgxrstr.setRawString(instEdit);
|
||||
m_wout.tab().pStyled(rgxrstr);
|
||||
if (currentLine)
|
||||
m_wout.p(" ").bg(ostd::ConsoleColors::Yellow).fg(ostd::ConsoleColors::Red).p(" <-- ");
|
||||
m_wout.nl();
|
||||
m_wout.reset();
|
||||
}
|
||||
|
||||
void DebuggerNew::colorCodeInstructions(const ostd::String& inst, bool currentLine, const DisassemblyList& labelList)
|
||||
{
|
||||
ostd::String instEditor = inst;
|
||||
ostd::String instBody = "";
|
||||
ostd::String instHead = inst;
|
||||
instEditor.trim();
|
||||
if (instEditor.contains(" "))
|
||||
{
|
||||
instHead = instEditor.new_substr(0, instEditor.indexOf(" "));
|
||||
instBody = instEditor.new_substr(instEditor.indexOf(" "));
|
||||
}
|
||||
if (currentLine)
|
||||
{
|
||||
m_wout.bg(ostd::ConsoleColors::Yellow).fg(ostd::ConsoleColors::Red);
|
||||
}
|
||||
else if (instHead == "call" || instHead == "ret" || instHead == "int" || instHead == "rti")
|
||||
m_wout.bg(ostd::ConsoleColors::BrightRed).fg(ostd::ConsoleColors::White);
|
||||
else if (instHead == "hlt" || instHead == "debug_break")
|
||||
m_wout.fg(ostd::ConsoleColors::Red);
|
||||
else if (instHead == "nop")
|
||||
m_wout.fg(ostd::ConsoleColors::Gray);
|
||||
else if(instHead.isNumeric())
|
||||
m_wout.fg(ostd::ConsoleColors::Magenta);
|
||||
else
|
||||
m_wout.fg(ostd::ConsoleColors::Yellow);
|
||||
m_wout.p(instHead.cpp_str());
|
||||
m_wout.reset();
|
||||
colorizeInstructionBody(instBody, currentLine, labelList);
|
||||
}
|
||||
|
||||
void DebuggerNew::printStep(void)
|
||||
{
|
||||
m_wout.clear();
|
||||
int32_t codeRegionSpan = (m_consoleSize.y / 2) - 1;
|
||||
auto codeRegion = findCodeRegion(debugger.code, debugger.currentAddress, codeRegionSpan);
|
||||
for (int32_t i = 0; i < codeRegion.size(); i++)
|
||||
{
|
||||
auto& _da = codeRegion[i];
|
||||
bool currentLine = _da.addr == debugger.currentAddress;
|
||||
ostd::String label = findSymbol(debugger.labels, _da.addr);
|
||||
bool specialSection = _da.code.startsWith("[") &&_da.code.endsWith("]");
|
||||
label.fixedLength(debugger.labelLineLength);
|
||||
m_wout.fg(ostd::ConsoleColors::Gray).p(label.cpp_str()).p(" ");
|
||||
if (currentLine)
|
||||
{
|
||||
m_wout.fg(ostd::ConsoleColors::Black).bg(ostd::ConsoleColors::Yellow).p(ostd::Utils::getHexStr(_da.addr, true, 2).cpp_str()).p(" ").reset();;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (specialSection)
|
||||
m_wout.fg(ostd::ConsoleColors::Cyan);
|
||||
else if (_da.code == "debug_break")
|
||||
m_wout.fg(ostd::ConsoleColors::Red);
|
||||
else
|
||||
m_wout.fg(ostd::ConsoleColors::BrightGray);
|
||||
m_wout.p(ostd::Utils::getHexStr(_da.addr, true, 2).cpp_str()).p(" ");
|
||||
}
|
||||
if (specialSection)
|
||||
m_wout.fg(ostd::ConsoleColors::Cyan).p(_da.code.cpp_str()).nl();
|
||||
colorCodeInstructions(_da.code, currentLine, debugger.labels);
|
||||
m_wout.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//General
|
||||
void DebuggerNew::onInitialize(void)
|
||||
{
|
||||
enableSignals();
|
||||
connectSignal(ostd::tBuiltinSignals::KeyReleased);
|
||||
connectSignal(ogfx::gui::RawTextInput::actionEventSignalID);
|
||||
connectSignal(ogfx::gui::Button::actionEventSignalID);
|
||||
enableMouseDragEvent(false);
|
||||
|
||||
// DisassemblyLoader::loadDirectory("disassembly");
|
||||
// m_codeTable = DisassemblyLoader::getCodeTable();
|
||||
// m_codeRandomIndex = ostd::Random::geti32(0, m_codeTable.size() - m_consoleSize.y - 1);
|
||||
|
||||
m_gfx.init(*this);
|
||||
m_gfx.setFont("res/Courier Prime.ttf");
|
||||
|
||||
float w = getWindowWidth();
|
||||
float h = 40.0f;
|
||||
m_textInput.create({ 0.0f, (float)(getWindowHeight() - h) }, { w, h }, "MainInputTXT");
|
||||
m_textInput.setEventListener(m_sigHandler);
|
||||
m_textInput.getTheme().extraPaddingTop = 3;
|
||||
|
||||
m_testBtn.create({ 100.0f, 100.0f }, { 120.0f, 90.0f }, "TestBTN");
|
||||
m_testBtn.setText("BTN");
|
||||
m_testBtn.setEventListener(m_btnSigHandler);
|
||||
|
||||
m_wout.attachWindow(*this);
|
||||
m_wout.setMonospaceFont("res/UbuntuMono-R.ttf");
|
||||
m_wout.setFontSize(22);
|
||||
m_wout.setConsoleMaxCharacters(m_consoleSize);
|
||||
m_wout.setConsolePosition(m_consolePosition);
|
||||
m_wout.setWrapMode(ogfx::WindowBaseOutputHandler::eWrapMode::TripleDots);
|
||||
m_wout.setDefaultForegroundColor({ 180, 180, 180, 255 });
|
||||
}
|
||||
|
||||
void DebuggerNew::handleSignal(ostd::tSignal& signal)
|
||||
{
|
||||
if (signal.ID == ostd::tBuiltinSignals::KeyReleased)
|
||||
{
|
||||
auto& evtData = (ogfx::KeyEventData&)signal.userData;
|
||||
if (evtData.keyCode == SDLK_ESCAPE)
|
||||
close();
|
||||
// else if (evtData.keyCode == SDLK_SPACE)
|
||||
// m_codeRandomIndex = ostd::Random::geti32(0, m_codeTable.size() - m_consoleSize.y - 1);
|
||||
}
|
||||
else if (signal.ID == ogfx::gui::RawTextInput::actionEventSignalID)
|
||||
{
|
||||
auto& data = (ogfx::gui::RawTextInput::ActionEventData&)signal.userData;
|
||||
if (data.senderName != "MainInputTXT")
|
||||
return;
|
||||
if (data.eventType == ogfx::gui::RawTextInput::eActionEventType::Enter)
|
||||
{
|
||||
out.fg(ostd::ConsoleColors::Green).p(data.sender.getText()).reset().nl();
|
||||
data.sender.setText("");
|
||||
}
|
||||
else if (data.eventType == ogfx::gui::RawTextInput::eActionEventType::Tab)
|
||||
{
|
||||
out.fg(ostd::ConsoleColors::Red).p("TAB").reset().nl();
|
||||
data.sender.appendText("TAB");
|
||||
}
|
||||
}
|
||||
else if (signal.ID == ogfx::gui::Button::actionEventSignalID)
|
||||
{
|
||||
auto& data = (ogfx::gui::Button::ActionEventData&)signal.userData;
|
||||
if (data.senderName != "TestBTN")
|
||||
return;
|
||||
if (data.eventType == ogfx::gui::Button::eActionEventType::Pressed)
|
||||
{
|
||||
out.fg(ostd::ConsoleColors::Green).p(data.sender.getText()).reset().nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerNew::onRender(void)
|
||||
{
|
||||
m_gfx.outlinedRect(m_wout.getConsoleBounds(), { 0, 0, 20, 255 }, { 255, 255, 255, 200 }, 2);
|
||||
|
||||
m_wout.beginFrame();
|
||||
printStep();
|
||||
// for (int32_t i = m_codeRandomIndex; i < m_codeRandomIndex + m_consoleSize.y; i++)
|
||||
// {
|
||||
// if (i >= m_codeTable.size()) break;
|
||||
// auto code = m_codeTable[i];
|
||||
// m_wout.tab().fg({ 100, 100, 100, 255 }).p(ostd::Utils::getHexStr(code.addr, true, 2));
|
||||
// m_wout.clear().tab().tab();
|
||||
// // colorCodeInstructions(code.code, m_wout);
|
||||
// }
|
||||
|
||||
// m_textInput.render(m_gfx);
|
||||
// m_testBtn.render(m_gfx);
|
||||
}
|
||||
|
||||
void DebuggerNew::onFixedUpdate(void)
|
||||
{
|
||||
m_textInput.fixedUpdate();
|
||||
m_testBtn.fixedUpdate();
|
||||
}
|
||||
|
||||
void DebuggerNew::onUpdate(void)
|
||||
{
|
||||
m_textInput.update();
|
||||
m_testBtn.update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint32_t __debugger_entry_point(void)
|
||||
{
|
||||
DebuggerNew window;
|
||||
window.initialize(1600, 1000, "DragonVM Live Debugger");
|
||||
window.setClearColor({ 0, 2 , 15 });
|
||||
|
||||
while (window.isRunning())
|
||||
{
|
||||
window.update();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
231
src/debugger/DebuggerNew.hpp
Normal file
231
src/debugger/DebuggerNew.hpp
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
#pragma once
|
||||
|
||||
#include <ostd/Color.hpp>
|
||||
#include <ostd/Geometry.hpp>
|
||||
#include <ostd/Utils.hpp>
|
||||
#include <ostd/IOHandlers.hpp>
|
||||
#include <ogfx/WindowBase.hpp>
|
||||
#include <ogfx/BasicRenderer.hpp>
|
||||
#include <ogfx/RawTextInput.hpp>
|
||||
#include <ogfx/WindowBaseOutputHandler.hpp>
|
||||
#include "../assembler/Assembler.hpp"
|
||||
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class Button : public ostd::Rectangle
|
||||
{
|
||||
public: class EventListener : public ostd::BaseObject
|
||||
{
|
||||
public: enum class eEventType { None = 0, MousePressed, KeyPressed, KeyReleased };
|
||||
public:
|
||||
EventListener(Button& _parent);
|
||||
virtual void handleSignal(ostd::tSignal& signal) override;
|
||||
inline virtual void onSignalHandled(ostd::tSignal& signal) { }
|
||||
inline Button& getParent(void) { return parent; }
|
||||
|
||||
private:
|
||||
Button& parent;
|
||||
eEventType m_lastEvent { eEventType::None };
|
||||
};
|
||||
public: class Theme
|
||||
{
|
||||
public:
|
||||
ostd::Color textColor { 0, 0, 0, 0 };
|
||||
ostd::Color borderColor { 0, 0, 0, 0 };
|
||||
ostd::Color backgroundColor { 0, 0, 0, 0 };
|
||||
|
||||
ostd::Color textColor_Hover { 0, 0, 0, 0 };
|
||||
ostd::Color borderColor_Hover { 0, 0, 0, 0 };
|
||||
ostd::Color backgroundColor_Hover { 0, 0, 0, 0 };
|
||||
|
||||
ostd::Color textColor_Pressed { 0, 0, 0, 0 };
|
||||
ostd::Color borderColor_Pressed { 0, 0, 0, 0 };
|
||||
ostd::Color backgroundColor_Pressed { 0, 0, 0, 0 };
|
||||
|
||||
int32_t fontSize { 0 };
|
||||
};
|
||||
public: struct tDefaultThemes
|
||||
{
|
||||
inline static const Theme DebugTheme {
|
||||
{ 220, 220, 255 }, //Text Color
|
||||
{ 10, 20, 120 }, //Border Color
|
||||
{ 0, 0, 22 }, //Background Color
|
||||
|
||||
{ 220, 220, 255 }, //Text Color Hover
|
||||
{ 10, 20, 120 }, //Border Color Hover
|
||||
{ 0, 0, 22 }, //Background Color Hover
|
||||
|
||||
{ 220, 220, 255 }, //Text Color Pressed
|
||||
{ 10, 20, 120 }, //Border Color Pressed
|
||||
{ 0, 0, 22 }, //Background Color Pressed
|
||||
|
||||
20 //Font Size
|
||||
};
|
||||
inline static const Theme DefaultTheme {
|
||||
{ 120, 120, 180 }, //Text Color
|
||||
{ 10, 20, 120 }, //Border Color
|
||||
{ 0, 2, 10 }, //Background Color
|
||||
|
||||
{ 120, 120, 210 }, //Text Color Hover
|
||||
{ 10, 20, 180 }, //Border Color Hover
|
||||
{ 0, 2, 50 }, //Background Color Hover
|
||||
|
||||
{ 120, 120, 120 }, //Text Color Pressed
|
||||
{ 10, 20, 60 }, //Border Color Pressed
|
||||
{ 0, 2, 0 }, //Background Color Pressed
|
||||
|
||||
20 //Font Size
|
||||
};
|
||||
};
|
||||
public: enum eActionEventType { None = 0, Pressed };
|
||||
public: class ActionEventData : public ostd::BaseObject
|
||||
{
|
||||
public:
|
||||
inline ActionEventData(Button& _sender, const ostd::String& _senderName, eActionEventType _eventType, ostd::BaseObject& _userData) :
|
||||
sender(_sender),
|
||||
senderName(_senderName),
|
||||
eventType(_eventType),
|
||||
userData(_userData)
|
||||
{
|
||||
setTypeName("ogfx::gui::Button::ActionEventData");
|
||||
validate();
|
||||
}
|
||||
|
||||
public:
|
||||
Button& sender;
|
||||
ostd::String senderName { "" };
|
||||
eActionEventType eventType { eActionEventType::None };
|
||||
ostd::BaseObject& userData { ostd::BaseObject::InvalidRef() };
|
||||
};
|
||||
|
||||
public:
|
||||
inline Button(void) { create({ 0.0f, 0.0f }, { 200.0f, 30.0f }, "UnnamedButton"); }
|
||||
inline Button(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name) { create(position, size, name); }
|
||||
Button& create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name);
|
||||
|
||||
virtual void render(ogfx::BasicRenderer2D& gfx);
|
||||
virtual void update(void);
|
||||
virtual void fixedUpdate(void);
|
||||
|
||||
virtual inline void onRender(ogfx::BasicRenderer2D& gfx) { }
|
||||
virtual inline void onUpdate(void) { }
|
||||
virtual inline void onFixedUpdate(void) { }
|
||||
|
||||
void setText(const ostd::String& text);
|
||||
void appendText(const ostd::String& text);
|
||||
void setTheme(Theme theme);
|
||||
|
||||
inline void setEventListener(EventListener& evtl) { m_eventListener = &evtl; }
|
||||
inline void setName(const ostd::String& name) { m_name = name; }
|
||||
|
||||
inline EventListener* getEventListener(void) const { return m_eventListener; }
|
||||
inline ostd::String getText(void) const { return m_text; }
|
||||
inline Theme& getTheme(void) { return m_theme; }
|
||||
inline ostd::String getName(void) const { return m_name; }
|
||||
inline bool isMouseInside(void) const { return m_mouseInside; }
|
||||
inline bool isPressed(void) const { return m_pressed; }
|
||||
|
||||
private:
|
||||
EventListener* m_eventListener { nullptr };
|
||||
ogfx::BasicRenderer2D* m_gfx { nullptr };
|
||||
|
||||
protected:
|
||||
ostd::String m_name { "" };
|
||||
ostd::String m_text { "" };
|
||||
Theme m_theme;
|
||||
bool m_mouseInside { false };
|
||||
bool m_pressed { false };
|
||||
|
||||
public:
|
||||
inline static const uint32_t actionEventSignalID { ostd::SignalHandler::newCustomSignal(12400) };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
typedef std::vector<dragon::code::Assembler::tDisassemblyLine> DisassemblyList;
|
||||
|
||||
class DebuggerNew : public ogfx::WindowBase
|
||||
{
|
||||
public: struct tCommandLineArgs
|
||||
{
|
||||
inline tCommandLineArgs(void) { }
|
||||
ostd::String machine_config_path = "";
|
||||
bool verbose_load = false;
|
||||
bool force_load = false;
|
||||
bool step_exec = false;
|
||||
bool track_step_diff = true;
|
||||
bool auto_start_debug = false;
|
||||
bool hide_virtual_display = true;
|
||||
bool track_call_stack = true;
|
||||
bool auto_track_all_data_symbols = true;
|
||||
ostd::String force_load_file = "";
|
||||
uint16_t force_load_mem_offset = 0x00;
|
||||
};
|
||||
public: struct tDebuggerData
|
||||
{
|
||||
inline tDebuggerData(void) { }
|
||||
tCommandLineArgs args;
|
||||
DisassemblyList code;
|
||||
DisassemblyList labels;
|
||||
DisassemblyList data;
|
||||
std::vector<uint16_t> trackedAddresses;
|
||||
ostd::String command;
|
||||
int32_t labelLineLength { 40 };
|
||||
uint16_t currentAddress { 0 };
|
||||
bool userQuit { false };
|
||||
ostd::String disassemblyDirectory { "disassembly" };
|
||||
std::vector<uint16_t> manualBreakPoints;
|
||||
};
|
||||
public:
|
||||
//Utils
|
||||
DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin);
|
||||
ostd::String findSymbol(const DisassemblyList& labels, uint16_t address, uint16_t* outSize = nullptr);
|
||||
uint16_t findSymbol(const DisassemblyList& labels, const ostd::String& symbol, uint16_t* outSize = nullptr);
|
||||
bool isValidLabelNameChar(char c);
|
||||
void removeBreakPoint(uint16_t addr);
|
||||
bool isBreakPoint(uint16_t addr);
|
||||
void addBreakPoint(uint16_t addr);
|
||||
|
||||
//Debugger
|
||||
void processErrors(void);
|
||||
int32_t loadArguments(int argc, char** argv);
|
||||
int32_t initRuntime(void);
|
||||
|
||||
//Display
|
||||
void colorizeInstructionBody(const ostd::String& instBody, bool currentLine, const DisassemblyList& labelList);
|
||||
void colorCodeInstructions(const ostd::String& inst, bool currentLine, const DisassemblyList& labelList);
|
||||
void printStep(void);
|
||||
|
||||
//General
|
||||
inline DebuggerNew(void) : m_sigHandler(m_textInput, *this), m_btnSigHandler(m_testBtn) { }
|
||||
void onInitialize(void) override;
|
||||
void handleSignal(ostd::tSignal& signal) override;
|
||||
void onRender(void) override;
|
||||
void onFixedUpdate(void) override;
|
||||
void onUpdate(void) override;
|
||||
|
||||
private:
|
||||
tDebuggerData debugger;
|
||||
ogfx::gui::RawTextInput m_textInput;
|
||||
ogfx::BasicRenderer2D m_gfx;
|
||||
ogfx::gui::RawTextInputEventListener m_sigHandler;
|
||||
ogfx::gui::RawTextInputNumberCharacterFilter m_numCharFilter;
|
||||
|
||||
ogfx::gui::Button m_testBtn;
|
||||
ogfx::gui::Button::EventListener m_btnSigHandler;
|
||||
|
||||
ogfx::WindowBaseOutputHandler m_wout;
|
||||
ostd::IPoint m_consoleSize { 300, 50 };
|
||||
ostd::Vec2 m_consolePosition { 650, 8 };
|
||||
// std::vector<code::Assembler::tDisassemblyLine> m_codeTable;
|
||||
// int32_t m_codeRandomIndex { 0 };
|
||||
|
||||
};
|
||||
|
||||
uint32_t __debugger_entry_point(void);
|
||||
}
|
||||
|
|
@ -1,26 +1,54 @@
|
|||
#include "Debugger.hpp"
|
||||
// #include "Debugger.hpp"
|
||||
#include "../runtime/DragonRuntime.hpp"
|
||||
#include "DebuggerNew.hpp"
|
||||
#include <ostd/Signals.hpp>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// //Loading commandline arguments
|
||||
// int32_t rValue = dragon::Debugger::loadArguments(argc, argv);
|
||||
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
// return 0;
|
||||
// if (rValue != 0) return rValue;
|
||||
|
||||
// //Initializing the runtime
|
||||
// rValue = dragon::Debugger::initRuntime();
|
||||
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
// return 0;
|
||||
// if (rValue != 0) return rValue;
|
||||
|
||||
// //Running top-level prompt
|
||||
// rValue = dragon::Debugger::topLevelPrompt();
|
||||
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
// return 0;
|
||||
// if (rValue != 0) return rValue;
|
||||
|
||||
// //Executing the runtime
|
||||
// return dragon::Debugger::executeRuntime();
|
||||
|
||||
|
||||
ostd::SignalHandler::init();
|
||||
|
||||
dragon::DebuggerNew debuggerInstance;
|
||||
debuggerInstance.initialize(2000, 1090, "DragonVM Live Debugger");
|
||||
debuggerInstance.setClearColor({ 5, 0, 0 });
|
||||
|
||||
//Loading commandline arguments
|
||||
int32_t rValue = dragon::Debugger::loadArguments(argc, argv);
|
||||
int32_t rValue = debuggerInstance.loadArguments(argc, argv);
|
||||
if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
return 0;
|
||||
if (rValue != 0) return rValue;
|
||||
|
||||
//Initializing the runtime
|
||||
rValue = dragon::Debugger::initRuntime();
|
||||
rValue = debuggerInstance.initRuntime();
|
||||
if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
return 0;
|
||||
if (rValue != 0) return rValue;
|
||||
|
||||
//Running top-level prompt
|
||||
rValue = dragon::Debugger::topLevelPrompt();
|
||||
if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
|
||||
return 0;
|
||||
if (rValue != 0) return rValue;
|
||||
|
||||
//Executing the runtime
|
||||
return dragon::Debugger::executeRuntime();
|
||||
while (debuggerInstance.isRunning())
|
||||
{
|
||||
debuggerInstance.update();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <ostd/IOHandlers.hpp>
|
||||
#include "GlobalData.hpp"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue