diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2269c46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.vscode/ +/makevars.mak diff --git a/README.md b/README.md index 64d0f41..2e7ac91 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ # spider-live-debug -The live debug is a program which runs the Spider Runtime VM in the terminal. Allows for editing code and running byte code, for example. \ No newline at end of file +The live debug is a program which runs the Spider Runtime VM in the terminal. Allows for editing code and running byte code, for example. + +--- + +This repository requires **spider-runtime** for the Spider VM and **Kittycannon/desktoplib** for the terminal. Please include these two before building this project. + +You will need to define their paths in `makevars.mak`. We currently use *static linking* for both. + +Needless to say, **spider-live-debug** requires a compliant terminal in order to use. diff --git a/bin/spider/DrawVM.d b/bin/spider/DrawVM.d new file mode 100644 index 0000000..96619c2 --- /dev/null +++ b/bin/spider/DrawVM.d @@ -0,0 +1,3 @@ +bin/spider/DrawVM.o: src/spider/DrawVM.cpp src/spider/LiveDebug.hpp +src/spider/DrawVM.cpp: +src/spider/LiveDebug.hpp: diff --git a/bin/spider/DrawVM.o b/bin/spider/DrawVM.o new file mode 100644 index 0000000..5374586 Binary files /dev/null and b/bin/spider/DrawVM.o differ diff --git a/bin/spider/LiveDebug.d b/bin/spider/LiveDebug.d new file mode 100644 index 0000000..04d593f --- /dev/null +++ b/bin/spider/LiveDebug.d @@ -0,0 +1,3 @@ +bin/spider/LiveDebug.o: src/spider/LiveDebug.cpp src/spider/LiveDebug.hpp +src/spider/LiveDebug.cpp: +src/spider/LiveDebug.hpp: diff --git a/bin/spider/LiveDebug.o b/bin/spider/LiveDebug.o new file mode 100644 index 0000000..c0cf375 Binary files /dev/null and b/bin/spider/LiveDebug.o differ diff --git a/makefile b/makefile new file mode 100644 index 0000000..7242959 --- /dev/null +++ b/makefile @@ -0,0 +1,78 @@ +# Include variables from user defined +# makevars.mak for paths & other stuff. +include makevars.mk + +#Compiler and Linker +CC := g++ + +#The Target Binary Program +TARGET := out.exe + +#The Directories, Source, Includes, Objects, Binary and Resources +SRCDIR := src +BUILDDIR := bin +TARGETDIR := out +SRCEXT := cpp +DEPEXT := d +OBJEXT := o + +#Flags, Libraries and Includes +ROOT := ./ +CFLAGS := -std=c++20 -O2 \ + -Wall -Werror -Wextra \ + -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align \ + -Wunused -Woverloaded-virtual -Wconversion \ + -Wsign-conversion -Wnull-dereference -Wdouble-promotion \ + -Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \ + -Wextra-semi -Wduplicated-cond -Wduplicated-branches \ + -Wlogical-op -Wuseless-cast +LFLAGS := -std=c++20 -static -static-libstdc++ -static-libgcc \ + -Wl,--fatal-warnings -Wl,--warn-common +LIBDIRS := -L"$(PATH_DESKTOPLIB)/out" -L"$(PATH_SPIDER_RUNTIME)/out" +LIB := -ldesktoplib #-lspider-runtime +INC := -I"$(PATH_DESKTOPLIB)/src" -I"$(PATH_SPIDER_RUNTIME)/src" -I./src/ + +#--------------------------------------------------------------------------------- +# DO NOT EDIT BELOW THIS LINE +#--------------------------------------------------------------------------------- +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT))) + +#Defauilt Make +all: directories $(TARGET) + +#Remake +remake: cleaner all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +#Clean only Objecst +clean: + @$(RM) -rf $(BUILDDIR) + +#Full Clean, Objects and Binaries +cleaner: clean + @$(RM) -rf $(TARGETDIR) + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) + $(CC) $(LFLAGS) -o $(TARGETDIR)/$(TARGET) $^ $(LIBDIRS) $(LIB) + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< + @$(CC) $(CFLAGS) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +#Non-File Targets +.PHONY: all remake clean cleaner resources diff --git a/makevars.mk b/makevars.mk new file mode 100644 index 0000000..e69f4de --- /dev/null +++ b/makevars.mk @@ -0,0 +1,3 @@ +# DEFINE spider runtime and desktoplib locations! +PATH_SPIDER_RUNTIME := ./../spider-runtime +PATH_DESKTOPLIB := ./../../desktoplib diff --git a/out/out.exe b/out/out.exe new file mode 100644 index 0000000..1d47660 Binary files /dev/null and b/out/out.exe differ diff --git a/spider-live-debug.code-workspace b/spider-live-debug.code-workspace new file mode 100644 index 0000000..59f593f --- /dev/null +++ b/spider-live-debug.code-workspace @@ -0,0 +1,25 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "gitlens.remotes": [ + { + "domain": "git.sintekanalytics.com", + "type": "Gitea", + "name": "Sintek Analytics' Git", + "protocol": "https", + } + ], + // Friendly reminder to alter the includepath + // in YOUR OWN .vscode/settings.json + "C_Cpp.default.includePath": [ + "./src" + ], + "terminal.integrated.defaultProfile.windows": "MSYS2 UCRT", + "terminal.integrated.gpuAcceleration": "off", + "terminal.integrated.minimumContrastRatio": 1 + } +} diff --git a/src/spider/DrawVM.cpp b/src/spider/DrawVM.cpp new file mode 100644 index 0000000..c6d384f --- /dev/null +++ b/src/spider/DrawVM.cpp @@ -0,0 +1,220 @@ +#include "LiveDebug.hpp" + +#include +#include + +#include + +namespace spider { + + void drawU64(u64 n) { + const char chars[] = { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F', + }; + Terminal& t = *term; + for (int i = 15; i >= 0; --i) { + u64 m = n >> (i * 4); + t << chars[m & 0xF]; + } + } + + void drawCPUFace() { + Terminal& t = *term; + + i32 c = 1, r = 8; + i32 w = 35, h = 31; + Box myBox({ c, r }, w, h, " CPU "); + myBox.charset = BoxSet::DOUBLE; + myBox.borderFg = color::CYAN; + + t << myBox; + + const std::string regs[] = { + "RA", "RB", "RC", "RD", + "RX", "RY", "R0", "R1", + "R2", "R3", "R4", "R5", + "R6", "R7", "R8", "R9", + "RF", "RI", "RS", "RZ", + "RE", "RN", "RV", "RM", + "ALU0", "ALU1" + }; + const color alt[] = { + color::WHITE, + color::B_BLACK, + }; + + r++; + c++; + + t + << pos(c, r++) + << color::B_YELLOW + ; + t.center(w - 2, "GP Registers"); + t << style::RESET; + for (i32 i = 0; i < 8; i++) { + t + << alt[i & 1] + << pos(c, r + i * 2) + << regs[i * 2] + << pos(c + 17, r + i * 2) + << regs[i * 2 + 1] + ; + } + + t << pos(c, r += 16); + t << color::B_CYAN; + t.center(w - 2, "System Registers"); + t << style::RESET; + r++; + for (i32 j = 0, i = 8; i < 12; j++, i++) { + t + << alt[j & 1] + << pos(c, r + j * 2) + << regs[i * 2] + << pos(c + 17, r + j * 2) + << regs[i * 2 + 1] + ; + } + + t << pos(c, r += 8); + t << color::GREEN; // <[CPU]> + t.center(w - 2, "VM Registers"); + t << style::RESET; + r++; + for (i32 j = 0, i = 12; i < 13; j++, i++) { + t << alt[j & 1]; + t << pos(c, r + j * 2); + t << regs[i * 2]; + t << pos(c + 17, r + j * 2); + t << regs[i * 2 + 1]; + } + + t.flush(); + } + + void drawRAMFace() { + Terminal& t = *term; + // FF FF FF FF FF FF FF FF | XXXX XXXX #// + + i32 c = 37, r = 8; + i32 w = 40, h = 31; + Box myBox({ c, r }, w, h, " RAM "); + myBox.charset = BoxSet::DOUBLE; + myBox.borderFg = color::RED; + + t << myBox; + } + + void drawByteCodeFace() { + Terminal& t = *term; + // FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | XXXXXXXX XXXXXXXX #// + + i32 c = 78, r = 8; + i32 w = 71, h = 31; + Box myBox({ c, r }, w, h, " Byte Code "); + myBox.charset = BoxSet::DOUBLE; + myBox.borderFg = color::GREEN; + + t << myBox; + } + + std::string getTime() { + std::time_t t = std::time(nullptr); + std::tm lt; +#if defined(SPIDER_OS_WINDOWS) + localtime_s(<, &t); +#endif +#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS) + localtime_r(&t, <); +#endif + return std::format("{:02}:{:02}:{:02} {:02}/{:02}/{}", + lt.tm_hour, lt.tm_min, lt.tm_sec, + lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900); + } + + void drawFaceplate() { + Terminal& t = *term; + t + << style::RESET + << color::B_YELLOW << " Spider Runtime Live Debug " + << style::RESET << " | " + << color::B_CYAN << " Sintek Analytics @ 2026 " + << style::RESET << " | " + << color::B_BLACK << "Press ESC to exit" + << style::RESET << " | " + << color::WHITE << getTime() + << style::RESET << " | " + << color::BLACK + << backg::YELLOW + << pos(1, 3) << " // __ \\\\" << " " + << pos(1, 4) << " \\\\( )//" << " SPIDER v0.1 " + << pos(1, 5) << " //()\\\\ " << " alpha " + << pos(1, 6) << " \\\\ // " << " " + << style::RESET + << pos(29, 3) << color::B_BLACK << "[ STEP ]" << color::WHITE << " Cycles: " << color::B_YELLOW << "0" + << pos(29, 4) << color::B_BLACK << "[ RUN ]" << color::WHITE << " State : " << color::B_YELLOW << "Stand By" + << pos(29, 5) << color::B_BLACK << "[ STOP ]" << color::WHITE << " Type : " << color::B_YELLOW << "n/a" + << pos(29, 6) << color::B_BLACK << "[ MENU ]" << color::WHITE << " Value : " << color::B_YELLOW << "n/a" + << style::RESET + ; + drawCPUFace(); + drawRAMFace(); + drawByteCodeFace(); + t << pos(101, 1) << color::YELLOW; + for(int i = 0; i < 47; i++) t << "═"; + t << "╗"; + for(int i = 0; i < 5; i++) { + t << move(-1, 1) << "║"; + } + t << move(-1, 1) << style::RESET << "-"; + } + + void drawMainMenuSel() { + Terminal& t = *term; + t + << pos(29, 3) << color::B_BLACK << "[ STEP ]" + << pos(29, 4) << color::B_BLACK << "[ RUN ]" + << pos(29, 5) << color::B_BLACK << "[ STOP ]" + << pos(29, 6) << color::B_BLACK << "[ MENU ]" + << pos(4, 8) << color::CYAN << " CPU " + << pos(40, 8) << color::RED << " RAM " + << pos(81, 8) << color::GREEN << " Byte Code " + ; + switch(mainMenuID) { + case 0x1: // step + t << pos(29, 3) << color::CYAN << style::BOLD << "[>STEP<]"; + break; + case 0x2: // run + t << pos(29, 4) << color::CYAN << style::BOLD << "[>RUN <]"; + break; + case 0x3: // stop + t << pos(29, 5) << color::CYAN << style::BOLD << "[>STOP<]"; + break; + case 0x4: // menu + t << pos(29, 6) << color::CYAN << style::BOLD << "[>MENU<]"; + break; + case 0x11: // cpu // y=7 + t << pos(4, 8) << color::CYAN << style::BOLD; + if(menuSelected) t << "[ CPU ]"; + else t << "> CPU <"; + break; + case 0x12: // ram + t << pos(40, 8) << color::RED << style::BOLD; + if(menuSelected) t << "[ RAM ]"; + else t << "> RAM <"; + break; + case 0x13: // instr + t << pos(81, 8) << color::GREEN << style::BOLD; + if(menuSelected) t << "[ Byte Code ]"; + else t << "> Byte Code <"; + break; + } + t << style::RESET; + t.flush(); + } + +} diff --git a/src/spider/LiveDebug.cpp b/src/spider/LiveDebug.cpp new file mode 100644 index 0000000..855c108 --- /dev/null +++ b/src/spider/LiveDebug.cpp @@ -0,0 +1,117 @@ +#include "LiveDebug.hpp" + +#include + +namespace spider { + + // Resources // + Terminal* term; + MenuMap* mainmenu; + + bool running; + int mainMenuID = 1; + int intrMenuID = 1; + + bool menuSelected = false; + int selCPUReg = 0; + int selRamPos = 0; + int selInstrPos = 0; + + // UI Actions // + u64 cyclesRan = 0; + bool runVM = false; + + void clearAll() { + Terminal& t = *term; + t + .altbuff(true) + .cursor(false) + .cls() + .fill(backg::BLACK) + ; + drawFaceplate(); + } + + // Live Actions // + + void runOne() { + cyclesRan++; + } + + void startRunning() { + runVM = true; + } + + void stopRunning() { + runVM = false; + } + + // Setup & Loop // + + void setup() { + clearAll(); + mainmenu = new MenuMap(3, 5); + mainmenu->setWrap(true, false); + + mainmenu->fill(0, 0, 3, 1, 0x1); + mainmenu->fill(0, 1, 3, 1, 0x2); + mainmenu->fill(0, 2, 3, 1, 0x3); + mainmenu->fill(0, 3, 3, 1, 0x4); + + mainmenu->fill(0, 4, 1, 3, 0x11); + mainmenu->fill(1, 4, 1, 3, 0x12); + mainmenu->fill(2, 4, 1, 3, 0x13); + } + + void mainMenuCtrls(int k) { + switch(k) { + case key::UP: + mainmenu->moveUp(); + break; + case key::DOWN: + mainmenu->moveDown(); + break; + case key::LEFT: + mainmenu->moveLeft(); + break; + case key::RIGHT: + mainmenu->moveRight(); + break; + default: + return; + } + auto r = mainmenu->getCursor(); + mainMenuID = r.id; + } + + void loop() { + // time @79 + Terminal& t = *term; + t << style::RESET << pos(79, 1) << getTime(); + + // Check quit? + int k = term->getKeyNb(); + if(k == key::ESC) { + running = false; + return; + } + mainMenuCtrls(k); + drawMainMenuSel(); + + // Favour the thread doing other stuff + if(!runVM) { // IF the vm is not continously running + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + } + +} + +int main() { + spider::term = new spider::Terminal(); + spider::running = true; + spider::setup(); + while(spider::running) spider::loop(); + spider::term->cursor(true).altbuff(false); + return 0; +} diff --git a/src/spider/LiveDebug.hpp b/src/spider/LiveDebug.hpp new file mode 100644 index 0000000..dcbf345 --- /dev/null +++ b/src/spider/LiveDebug.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include +#include + +namespace spider { + + using namespace ckitty::terminal; + + // Resources // + extern Terminal* term; + extern MenuMap* mainmenu; + extern bool running; + extern int mainMenuID; + extern bool menuSelected; + + // UI Actions // + + void clearAll(); + + void drawFaceplate(); + + void drawMainMenuSel(); + + std::string getTime(); + + // Live Actions // + + void runOne(); + +}