Preparation for building instructions
This commit is contained in:
@@ -2,33 +2,45 @@
|
||||
|
||||
#include <spider/runtime/Runtime.hpp>
|
||||
#include <spider/runtime/util/Terminal.hpp>
|
||||
#include <spider/runtime/native/distro.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
#include <thread>
|
||||
namespace spider {
|
||||
|
||||
void drawHead(Terminal& t) {
|
||||
t.move(1, 1)
|
||||
.style(Terminal::RESET)
|
||||
.print(" Spider Runtime Live Debug ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_CYAN).print(" Sintek Analytics @ 2026 ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_B_BLACK).print("Press ESC to exit")
|
||||
.style(Terminal::FG_BLACK)
|
||||
.style(Terminal::BG_YELLOW)
|
||||
.move(3, 1).print(" || __ ||").print(" ")
|
||||
.move(4, 1).print(" \\\\( )//").print(" SPIDER v0.1 ")
|
||||
.move(5, 1).print(" //()\\\\ ").print(" alpha ")
|
||||
.move(6, 1).print(" || || ").print(" ")
|
||||
.style(Terminal::RESET)
|
||||
;
|
||||
.style(Terminal::FG_YELLOW)
|
||||
.print(" Spider Runtime Live Debug ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_B_CYAN).print(" Sintek Analytics @ 2026 ")
|
||||
.style(Terminal::RESET).print(" | ")
|
||||
.style(Terminal::FG_B_BLACK).print("Press ESC to exit")
|
||||
.style(Terminal::FG_BLACK)
|
||||
.style(Terminal::BG_YELLOW)
|
||||
.move(3, 1).print(" // __ \\\\").print(" ") // 27
|
||||
.move(4, 1).print(" \\\\( )//").print(" SPIDER v0.1 ")
|
||||
.move(5, 1).print(" //()\\\\ ").print(" alpha ")
|
||||
.move(6, 1).print(" \\\\ // ").print(" ")
|
||||
.style(Terminal::RESET)
|
||||
.style(Terminal::FG_B_BLACK) // 4x8 for the menu
|
||||
.move(3, 28).print("[ STEP ]")
|
||||
.move(4, 28).print("[ STOP ]")
|
||||
.move(5, 28).print("[ RUN ]")
|
||||
.move(6, 28).print("[ MENU ]")
|
||||
.style(Terminal::RESET)
|
||||
;
|
||||
}
|
||||
|
||||
void drawCPUTempl(Terminal& t, CPU& cpu) {
|
||||
i32 r = 7, c = 1;
|
||||
t.drawBox(r, c, 35, 18, "CPU");
|
||||
i32 r = 8, c = 1;
|
||||
i32 w = 35, h = 31;
|
||||
t.drawBox(r, c, w, h, "CPU");
|
||||
|
||||
const std::string regs[] = {
|
||||
"RA", "RB", "RC", "RD",
|
||||
@@ -36,47 +48,335 @@ namespace spider {
|
||||
"R2", "R3", "R4", "R5",
|
||||
"R6", "R7", "R8", "R9",
|
||||
"RF", "RI", "RS", "RZ",
|
||||
"RE", "RN", "RV", "RM"
|
||||
"RE", "RN", "RV", "RM",
|
||||
"ALU0", "ALU1"
|
||||
};
|
||||
const std::string alt[] = {
|
||||
Terminal::FG_WHITE,
|
||||
Terminal::FG_B_BLACK,
|
||||
};
|
||||
|
||||
r++;
|
||||
c++;
|
||||
|
||||
|
||||
|
||||
for(i32 i = 0; i < 8; i++) {
|
||||
t.move(r++, c);
|
||||
t.style(Terminal::FG_B_YELLOW);
|
||||
t.print_center(w - 2, "GP Registers");
|
||||
t.style(Terminal::RESET);
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
t.style(alt[i & 1]);
|
||||
t.move(r + i * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + i * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 16, c);
|
||||
t.style(Terminal::FG_B_CYAN);
|
||||
t.print_center(w - 2, "System Registers");
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 j = 0, i = 8; i < 12; j++, i++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 8, c);
|
||||
t.style(Terminal::FG_GREEN);
|
||||
t.print_center(w - 2, "Extra Registers");
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 j = 0, i = 12; i < 13; j++, i++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
t.print(regs[i * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
t.print(regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.flush();
|
||||
}
|
||||
|
||||
void printU64Hex(u64 n) {
|
||||
std::ios state(nullptr);
|
||||
state.copyfmt(std::cout);
|
||||
std::cout
|
||||
<< std::hex
|
||||
<< std::uppercase
|
||||
<< std::setfill('0')
|
||||
<< std::setw(16)
|
||||
<< n;
|
||||
std::cout.copyfmt(state);
|
||||
}
|
||||
|
||||
void drawCPU(Terminal& t, CPU& cpu) {
|
||||
i32 r = 8, c = 1;
|
||||
|
||||
const register_t* regs[] = {
|
||||
&cpu.RA, &cpu.RB, &cpu.RC, &cpu.RD,
|
||||
&cpu.RX, &cpu.RY, &cpu.R0, &cpu.R1,
|
||||
&cpu.R2, &cpu.R3, &cpu.R4, &cpu.R5,
|
||||
&cpu.R6, &cpu.R7, &cpu.R8, &cpu.R9,
|
||||
//&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
|
||||
//&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
|
||||
&cpu.ALU0, &cpu.ALU1
|
||||
};
|
||||
const u64* sys_regs[] = {
|
||||
&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
|
||||
&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
|
||||
};
|
||||
const std::string alt[] = {
|
||||
Terminal::FG_WHITE,
|
||||
Terminal::FG_B_BLACK,
|
||||
};
|
||||
|
||||
r++;
|
||||
c++;
|
||||
t.move(r++, c);
|
||||
t.style(Terminal::RESET);
|
||||
r++;
|
||||
for (i32 i = 0; i < 8; i++) {
|
||||
t.style(alt[i & 1]);
|
||||
t.move(r + i * 2, c);
|
||||
printU64Hex(regs[i * 2]->_u64);
|
||||
t.move(r + i * 2, c + 17);
|
||||
printU64Hex(regs[i * 2 + 1]->_u64);
|
||||
}
|
||||
|
||||
t.move(r += 16, c);
|
||||
r++;
|
||||
for (i32 j = 0, i = 8; i < 12; j++, i++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
printU64Hex(*sys_regs[i * 2]);
|
||||
t.move(r + j * 2, c + 17);
|
||||
printU64Hex(*sys_regs[i * 2 + 1]);
|
||||
}
|
||||
|
||||
t.move(r += 8, c);
|
||||
r++;
|
||||
for (i32 j = 0; j < 1; j++) {
|
||||
t.style(alt[j & 1]);
|
||||
t.move(r + j * 2, c);
|
||||
printU64Hex(regs[16 + j * 2]->_u64);
|
||||
t.move(r + j * 2, c + 17);
|
||||
printU64Hex(regs[16 + j * 2 + 1]->_u64);
|
||||
}
|
||||
|
||||
t.flush();
|
||||
}
|
||||
|
||||
i32 addressWidth(isize ramSize) {
|
||||
if (ramSize == 0) return 1;
|
||||
isize maxAddr = ramSize - 1;
|
||||
i32 digits = 0;
|
||||
// Shift by increments of 4 (one hex nibble)
|
||||
// We use a do-while to ensure at least 1 digit is returned for small RAMs
|
||||
do {
|
||||
digits++;
|
||||
maxAddr >>= 4;
|
||||
} while (maxAddr > 0);
|
||||
|
||||
return digits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a vertical scrollbar
|
||||
* @param x The column where the bar should be placed (usually box_x + width - 1)
|
||||
* @param y The starting row of the track (usually box_y + 1)
|
||||
* @param trackHeight The internal height of the box (box_height - 2)
|
||||
* @param progress The current progress
|
||||
* @param total The total
|
||||
*/
|
||||
void drawScrollThumb(Terminal& term, i32 x, i32 y, i32 trackHeight, isize progress, isize total) {
|
||||
if (total == 0 || trackHeight <= 0) return;
|
||||
|
||||
// 1. Draw the background track (Light Shade: ░)
|
||||
term.style(Terminal::FG_B_BLACK); // Dim the track
|
||||
for (int i = 0; i < trackHeight; ++i) {
|
||||
term.move(y + i, x).print("░");
|
||||
}
|
||||
|
||||
// 2. Calculate Thumb Position
|
||||
// Cap progress to total to avoid overflow
|
||||
if (progress > total) progress = total;
|
||||
|
||||
// Calculate ratio (0.0 to 1.0)
|
||||
f64 ratio = f64(progress) / f64(total);
|
||||
|
||||
// Map to track coordinates
|
||||
i32 thumbOffset = i32(ratio * (trackHeight - 1));
|
||||
|
||||
// 3. Draw the Thumb (Full Block: █)
|
||||
term.move(y + thumbOffset, x);
|
||||
term.style(Terminal::FG_WHITE).print("█");
|
||||
term.style(Terminal::RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a hex dump of memory within a styled terminal box.
|
||||
* @param term Reference to your Terminal instance
|
||||
* @param ram The RAM
|
||||
* @param scrollPos The starting address to display
|
||||
* @param x Starting column
|
||||
* @param y Starting row
|
||||
* @param width Width of the box
|
||||
* @param height Height of the box
|
||||
*/
|
||||
void drawRAM(Terminal& term, RAM& ram, u64 scrollPos) {
|
||||
// 1. Draw the container box
|
||||
i32 y = 3;
|
||||
i32 height = 36;
|
||||
|
||||
// 2. Configuration for the hex layout
|
||||
int addrWidth = addressWidth(ram.size());
|
||||
int bytesPerRow = 8;
|
||||
int displayRows = height - 2; // Subtract top/bottom borders
|
||||
i32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth;
|
||||
i32 x = 37;
|
||||
|
||||
// create box
|
||||
term.drawBox(y, x, width, height, "RAM");
|
||||
drawScrollThumb(term, x + width - 2, y + 1, height - 2, scrollPos, ram.size());
|
||||
|
||||
// Ensure scrollPos is within bounds and aligned
|
||||
if (scrollPos < 0) scrollPos = 0;
|
||||
if (scrollPos > ram.size()) scrollPos = ram.size();
|
||||
|
||||
for (int i = 0; i < displayRows; ++i) {
|
||||
isize currentRowAddr = scrollPos + (i * bytesPerRow);
|
||||
|
||||
// address lock
|
||||
if (currentRowAddr >= ram.size()) {
|
||||
term.move(y + 1 + i, x + 1);
|
||||
term.print(std::string(width - 3, ' '));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ssaddr;
|
||||
std::stringstream ss;
|
||||
|
||||
// setup ss
|
||||
ssaddr << std::setfill('0') << std::uppercase << std::hex;
|
||||
ss << std::setfill('0') << std::uppercase << std::hex;
|
||||
|
||||
// address
|
||||
ssaddr << std::setw(addrWidth) << currentRowAddr << " ";
|
||||
|
||||
// Hex Bytes
|
||||
std::string asciiPart = "";
|
||||
for (int j = 0; j < bytesPerRow; ++j) {
|
||||
isize targetAddr = currentRowAddr + j;
|
||||
if (targetAddr >= ram.size()) {
|
||||
ss << ""; // Padding for end of memory
|
||||
asciiPart += "";
|
||||
continue;
|
||||
}
|
||||
|
||||
u8 byte = ram[targetAddr];
|
||||
ss << std::setfill('0') << std::setw(2) << std::hex << (u32)byte << " ";
|
||||
asciiPart += (std::isprint(byte) ? (char)byte : '.');
|
||||
}
|
||||
|
||||
// --- Combine and Print ---
|
||||
term.move(y + 1 + i, x + 2); // Move inside the box
|
||||
term.style(Terminal::FG_B_CYAN).print(ssaddr.str()); // Hex part in Cyan
|
||||
term.style(Terminal::FG_WHITE).print(ss.str());
|
||||
term.style(Terminal::FG_B_YELLOW).print(" | ");
|
||||
term.style(Terminal::FG_WHITE).print(asciiPart); // ASCII part in White
|
||||
}
|
||||
|
||||
term.style(Terminal::RESET);
|
||||
term.flush();
|
||||
}
|
||||
|
||||
std::string getTimestamp() {
|
||||
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 drawTime(Terminal& t) {
|
||||
//auto now = std::chrono::system_clock::now();
|
||||
//auto now_l = std::chrono::current_zone()->to_local(now);
|
||||
//auto now_s = std::chrono::floor<std::chrono::seconds>(now_l);
|
||||
//std::string time_str = std::format("{:%H:%M:%S}", now_s); // Format: HH:mm:ss
|
||||
//std::string date_str = std::format("{:%d/%m/%Y}", now_s); // Format: dd/MM/YYYY
|
||||
|
||||
t.move(1, 76);
|
||||
t.style(Terminal::RESET);
|
||||
t.print(" | ").style(Terminal::FG_GREEN).print(getTimestamp());
|
||||
}
|
||||
|
||||
void redraw(Terminal& t, Runtime& r, u64 scroll) {
|
||||
// draw CPU, RAM
|
||||
drawCPU(t, r.cpu);
|
||||
drawRAM(t, r.ram, scroll);
|
||||
}
|
||||
|
||||
int liveDebugMain() {
|
||||
Terminal t;
|
||||
Runtime runtime(1024);
|
||||
|
||||
bool running = true, update = true;
|
||||
u64 ramScroll = 0;
|
||||
u8 key = Terminal::UNKNOWN;
|
||||
|
||||
t.println("Starting Spider live debug...");
|
||||
t.altbuff(true).cursor(false);
|
||||
|
||||
drawTime(t);
|
||||
drawHead(t);
|
||||
drawCPUTempl(t, runtime.cpu);
|
||||
|
||||
bool running = true;
|
||||
int c = 1;
|
||||
// delay for time
|
||||
auto last_exec = std::chrono::steady_clock::now();
|
||||
auto delay = std::chrono::milliseconds(1000);
|
||||
|
||||
while (running) {
|
||||
// draw time
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now - last_exec >= delay) {
|
||||
drawTime(t);
|
||||
last_exec = now;
|
||||
}
|
||||
|
||||
// redraw something if it updated
|
||||
if (update) {
|
||||
redraw(t, runtime, ramScroll);
|
||||
update = false;
|
||||
}
|
||||
|
||||
// Handle Input
|
||||
u8 k = t.getKey();
|
||||
switch (k) {
|
||||
key = t.getKeyNb();
|
||||
switch (key) {
|
||||
case Terminal::ESC:
|
||||
running = false;
|
||||
break;
|
||||
case Terminal::UP:
|
||||
if (ramScroll >= 16) ramScroll -= 16;
|
||||
update = true;
|
||||
break;
|
||||
case Terminal::DOWN:
|
||||
if (runtime.ram.size() >= 16 && ramScroll <= runtime.ram.size() - 16) ramScroll += 16;
|
||||
update = true;
|
||||
break;
|
||||
default:
|
||||
t.move(5, c++);
|
||||
t.print("A");
|
||||
t.flush();
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
t.altbuff(false).println("Stopped Spider live debug.").flush();
|
||||
|
||||
Reference in New Issue
Block a user