added editable byte code
This commit is contained in:
@@ -1,2 +1,4 @@
|
|||||||
/.vscode/
|
/.vscode/
|
||||||
/makevars.mak
|
/makevars.mak
|
||||||
|
/bin
|
||||||
|
/out
|
||||||
|
|||||||
+4
-1
@@ -1,3 +1,6 @@
|
|||||||
bin/spider/DrawVM.o: src/spider/DrawVM.cpp src/spider/LiveDebug.hpp
|
bin/spider/DrawVM.o: src/spider/DrawVM.cpp src/spider/LiveDebug.hpp \
|
||||||
|
src/spider/RamContent.hpp src/spider/ByteCodeContent.hpp
|
||||||
src/spider/DrawVM.cpp:
|
src/spider/DrawVM.cpp:
|
||||||
src/spider/LiveDebug.hpp:
|
src/spider/LiveDebug.hpp:
|
||||||
|
src/spider/RamContent.hpp:
|
||||||
|
src/spider/ByteCodeContent.hpp:
|
||||||
|
|||||||
Binary file not shown.
@@ -1,3 +1,6 @@
|
|||||||
bin/spider/LiveDebug.o: src/spider/LiveDebug.cpp src/spider/LiveDebug.hpp
|
bin/spider/LiveDebug.o: src/spider/LiveDebug.cpp src/spider/LiveDebug.hpp \
|
||||||
|
src/spider/RamContent.hpp src/spider/ByteCodeContent.hpp
|
||||||
src/spider/LiveDebug.cpp:
|
src/spider/LiveDebug.cpp:
|
||||||
src/spider/LiveDebug.hpp:
|
src/spider/LiveDebug.hpp:
|
||||||
|
src/spider/RamContent.hpp:
|
||||||
|
src/spider/ByteCodeContent.hpp:
|
||||||
|
|||||||
Binary file not shown.
@@ -25,11 +25,11 @@ CFLAGS := -std=c++20 -O2 \
|
|||||||
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \
|
-Wsign-conversion -Wnull-dereference -Wdouble-promotion \
|
||||||
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
|
-Wformat=2 -Wimplicit-fallthrough -Wsuggest-override \
|
||||||
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \
|
-Wextra-semi -Wduplicated-cond -Wduplicated-branches \
|
||||||
-Wlogical-op -Wuseless-cast
|
-Wlogical-op -Wuseless-cast -Wno-unused-parameter
|
||||||
LFLAGS := -std=c++20 -static -static-libstdc++ -static-libgcc \
|
LFLAGS := -std=c++20 -static -static-libstdc++ -static-libgcc \
|
||||||
-Wl,--fatal-warnings -Wl,--warn-common
|
-Wl,--fatal-warnings -Wl,--warn-common
|
||||||
LIBDIRS := -L"$(PATH_DESKTOPLIB)/out" -L"$(PATH_SPIDER_RUNTIME)/out"
|
LIBDIRS := -L"$(PATH_DESKTOPLIB)/out" -L"$(PATH_SPIDER_RUNTIME)/out"
|
||||||
LIB := -ldesktoplib #-lspider-runtime
|
LIB := -ldesktoplib -lspider-runtime
|
||||||
INC := -I"$(PATH_DESKTOPLIB)/src" -I"$(PATH_SPIDER_RUNTIME)/src" -I./src/
|
INC := -I"$(PATH_DESKTOPLIB)/src" -I"$(PATH_SPIDER_RUNTIME)/src" -I./src/
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -0,0 +1,71 @@
|
|||||||
|
#include "ByteCodeContent.hpp"
|
||||||
|
|
||||||
|
#include "LiveDebug.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
ByteCodeContent::ByteCodeContent() : input(1), ipX(0), ipY(0) {}
|
||||||
|
|
||||||
|
ByteCodeContent::~ByteCodeContent() {}
|
||||||
|
|
||||||
|
// Content must report how tall it wants to be
|
||||||
|
int ByteCodeContent::getTotalHeight() const {
|
||||||
|
return int(std::ceil(float(reel.size() + 1) / 16.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render only the rows between startRow and endRow
|
||||||
|
// relativeY is where the Content starts drawing in terminal space
|
||||||
|
void ByteCodeContent::render(Terminal& t, pos screenPos, pos viewport, std::pair<int, int> rows) const {
|
||||||
|
const u64 reel_size = reel.size();
|
||||||
|
char ascii[16];
|
||||||
|
|
||||||
|
for (int row = rows.first; row < rows.second; ++row) {
|
||||||
|
// Set terminal cursor position for the start of this row
|
||||||
|
t << pos(screenPos.x + 1, screenPos.y + (row - rows.first));
|
||||||
|
|
||||||
|
// Group 8 Bytes
|
||||||
|
for(int block = 0; block < 2; block++) {
|
||||||
|
for (int col = 0; col < 8; ++col) {
|
||||||
|
u64 offset = u64(row * 16 + col + block * 8);
|
||||||
|
u32 offX = u32(block * 8 + col);
|
||||||
|
int ascii_index = col + block * 8;
|
||||||
|
|
||||||
|
// Is currently selected thing?
|
||||||
|
bool selected = offX == ipX && u32(row) == ipY && menuSelected && mainMenuID == 0x13;
|
||||||
|
if(selected) t << backg::B_GREEN << color::BLACK;
|
||||||
|
|
||||||
|
// Is input currently enabled?
|
||||||
|
if(input.getCharCount() && selected) {
|
||||||
|
// draw this instead!
|
||||||
|
u8 byte = u8(input.getValue());
|
||||||
|
drawU8(byte);
|
||||||
|
ascii[ascii_index] = (byte >= 32 && byte <= 126) ? static_cast<char>(byte) : '.';
|
||||||
|
} else if (offset < reel_size) {
|
||||||
|
u8 byte = reel.readU8(offset);
|
||||||
|
drawU8(byte);
|
||||||
|
ascii[ascii_index] = (byte >= 32 && byte <= 126) ? static_cast<char>(byte) : '.';
|
||||||
|
} else {
|
||||||
|
t << " ";
|
||||||
|
ascii[ascii_index] = ' ';
|
||||||
|
}
|
||||||
|
t << style::RESET << color::WHITE;
|
||||||
|
t << ' ';
|
||||||
|
}
|
||||||
|
if(block == 0) t << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
t << color::B_BLACK;
|
||||||
|
t << "| ";
|
||||||
|
t << color::WHITE;
|
||||||
|
|
||||||
|
// --- ASCII Output Loop ---
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
t << ascii[i];
|
||||||
|
if (i == 7) t << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/Runtime.hpp>
|
||||||
|
#include <desktoplib/terminal/ui/Content.hpp>
|
||||||
|
|
||||||
|
#include <spider/ByteInput.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
using namespace ckitty::terminal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a specific part of the RAM.
|
||||||
|
*/
|
||||||
|
class ByteCodeContent : public Content {
|
||||||
|
public:
|
||||||
|
|
||||||
|
ByteInput input;
|
||||||
|
u64 ipX, ipY;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ByteCodeContent();
|
||||||
|
|
||||||
|
virtual ~ByteCodeContent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Content must report how tall it wants to be
|
||||||
|
virtual int getTotalHeight() const override;
|
||||||
|
|
||||||
|
// Render only the rows between startRow and endRow
|
||||||
|
// relativeY is where the Content starts drawing in terminal space
|
||||||
|
virtual void render(Terminal& t, pos screenPos, pos viewport, std::pair<int, int> rows) const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "ByteInput.hpp"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
ByteInput::ByteInput(u64 bytes)
|
||||||
|
: max_bytes(bytes), max_chars(max_bytes * 2),
|
||||||
|
current_char_count(0), accumulated_value(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ByteInput::hexCharToInt(char ch) const {
|
||||||
|
if (ch >= '0' && ch <= '9') return u8(ch - '0');
|
||||||
|
if (ch >= 'a' && ch <= 'f') return u8(ch - 'a' + 10);
|
||||||
|
if (ch >= 'A' && ch <= 'F') return u8(ch - 'A' + 10);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteInput::accept(char ch) {
|
||||||
|
if (current_char_count >= max_chars || !std::isxdigit(int(ch))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift left by 4 bits (1 hex nibble) and inject the new digit
|
||||||
|
accumulated_value = (accumulated_value << 4) | hexCharToInt(ch);
|
||||||
|
current_char_count++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 ByteInput::getValue() const {
|
||||||
|
if (current_char_count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pad remaining digits with zeros since entry started at MSB
|
||||||
|
std::size_t remaining_chars = max_chars - current_char_count;
|
||||||
|
return accumulated_value << (remaining_chars * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteInput::cancel() {
|
||||||
|
current_char_count = 0;
|
||||||
|
accumulated_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteInput::isComplete() const { return current_char_count == max_chars; }
|
||||||
|
|
||||||
|
std::size_t ByteInput::getCharCount() const { return current_char_count; }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/Runtime.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
class ByteInput {
|
||||||
|
private:
|
||||||
|
|
||||||
|
u64 max_bytes;
|
||||||
|
u64 max_chars;
|
||||||
|
u64 current_char_count;
|
||||||
|
u64 accumulated_value;
|
||||||
|
|
||||||
|
// Helper to convert a single hex char to its integer value
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Byte Input object.
|
||||||
|
* @param bytes The number of bytes to accept (capped at 8 to prevent uint64_t overflow).
|
||||||
|
*/
|
||||||
|
explicit ByteInput(u64 bytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
u8 hexCharToInt(char ch) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Accepts a character if it is a valid hex digit and capacity remains.
|
||||||
|
* @param ch The character to process.
|
||||||
|
* @return true if accepted, false if invalid or full.
|
||||||
|
*/
|
||||||
|
bool accept(char ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the numeric value of the current input.
|
||||||
|
* @return std::uint64_t The value, padded with trailing zeros if incomplete.
|
||||||
|
*/
|
||||||
|
u64 getValue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets the input buffer and index.
|
||||||
|
*/
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
// Inline getters for quick state checking
|
||||||
|
bool isComplete() const;
|
||||||
|
|
||||||
|
u64 getCharCount() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
+107
-15
@@ -7,17 +7,81 @@
|
|||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
|
const char hex_chars[] = {
|
||||||
|
'0', '1', '2', '3',
|
||||||
|
'4', '5', '6', '7',
|
||||||
|
'8', '9', 'A', 'B',
|
||||||
|
'C', 'D', 'E', 'F',
|
||||||
|
};
|
||||||
|
|
||||||
void drawU64(u64 n) {
|
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;
|
Terminal& t = *term;
|
||||||
for (int i = 15; i >= 0; --i) {
|
for (int i = 15; i >= 0; --i) {
|
||||||
u64 m = n >> (i * 4);
|
u64 m = n >> (i * 4);
|
||||||
t << chars[m & 0xF];
|
t << hex_chars[m & 0xF];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawU8(u8 n) {
|
||||||
|
Terminal& t = *term;
|
||||||
|
t << hex_chars[(n >> 4) & 0xF];
|
||||||
|
t << hex_chars[ n & 0xF];
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawValue(register_t r) {
|
||||||
|
//u64: 18446744073709551615 | u64: 18446744073709551615//
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearValue() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawCPUValues() {
|
||||||
|
Terminal& t = *term;
|
||||||
|
CPU& cpu = runtime.cpu;
|
||||||
|
|
||||||
|
i32 c = 1, r = 8;
|
||||||
|
c++;
|
||||||
|
r += 3;
|
||||||
|
|
||||||
|
const color alt[] = {
|
||||||
|
color::WHITE,
|
||||||
|
color::B_BLACK,
|
||||||
|
};
|
||||||
|
|
||||||
|
t << style::RESET;
|
||||||
|
for (i32 i = 0; i < 8; i++) {
|
||||||
|
t << alt[i & 1];
|
||||||
|
t << pos(c, r + i * 2);
|
||||||
|
drawU64(cpu.GPR[i * 2]._u64);
|
||||||
|
t << pos(c + 17, r + i * 2);
|
||||||
|
drawU64(cpu.GPR[i * 2 + 1]._u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
r += 17;
|
||||||
|
// "RF", "RI", "RS", "RZ",
|
||||||
|
// "RE", "RN", "RV", "RM",
|
||||||
|
const u64* sr[] = {
|
||||||
|
&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ,
|
||||||
|
&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM,
|
||||||
|
};
|
||||||
|
t << style::RESET;
|
||||||
|
for (i32 i = 0; i < 4; i++) {
|
||||||
|
t << alt[i & 1];
|
||||||
|
t << pos(c, r + i * 2);
|
||||||
|
drawU64(*sr[i * 2]);
|
||||||
|
t << pos(c + 17, r + i * 2);
|
||||||
|
drawU64(*sr[i * 2 + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
r += 9;
|
||||||
|
const register_t* cr[] = { &cpu.ALU0, &cpu.ALU1 };
|
||||||
|
t << style::RESET;
|
||||||
|
for (i32 i = 0; i < 1; i++) {
|
||||||
|
t << alt[i & 1];
|
||||||
|
t << pos(c, r + i * 2);
|
||||||
|
drawU64(cr[i * 2]->_u64);
|
||||||
|
t << pos(c + 17, r + i * 2);
|
||||||
|
drawU64(cr[i * 2 + 1]->_u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +160,19 @@ namespace spider {
|
|||||||
t.flush();
|
t.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawRAMValues() {
|
||||||
|
if(updateRAM) {
|
||||||
|
updateRAM = false;
|
||||||
|
ram_scroll->render(*term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void drawRAMFace() {
|
void drawRAMFace() {
|
||||||
Terminal& t = *term;
|
Terminal& t = *term;
|
||||||
// FF FF FF FF FF FF FF FF | XXXX XXXX #//
|
// FF FF FF FF FF FF FF FF | XXXX XXXX #//
|
||||||
|
|
||||||
i32 c = 37, r = 8;
|
i32 c = ram_scroll->position.x - 1, r = ram_scroll->position.y - 1;
|
||||||
i32 w = 40, h = 31;
|
i32 w = ram_scroll->width + 2, h = ram_scroll->height + 2;
|
||||||
Box myBox({ c, r }, w, h, " RAM ");
|
Box myBox({ c, r }, w, h, " RAM ");
|
||||||
myBox.charset = BoxSet::DOUBLE;
|
myBox.charset = BoxSet::DOUBLE;
|
||||||
myBox.borderFg = color::RED;
|
myBox.borderFg = color::RED;
|
||||||
@@ -109,12 +180,19 @@ namespace spider {
|
|||||||
t << myBox;
|
t << myBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawByteCodeValues() {
|
||||||
|
if(updateReel) {
|
||||||
|
updateReel = false;
|
||||||
|
reel_scroll->render(*term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void drawByteCodeFace() {
|
void drawByteCodeFace() {
|
||||||
Terminal& t = *term;
|
Terminal& t = *term;
|
||||||
// FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | XXXXXXXX XXXXXXXX #//
|
// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ........ ........ #//
|
||||||
|
|
||||||
i32 c = 78, r = 8;
|
i32 c = reel_scroll->position.x - 1, r = reel_scroll->position.y - 1;
|
||||||
i32 w = 71, h = 31;
|
i32 w = reel_scroll->width + 2, h = reel_scroll->height + 2;
|
||||||
Box myBox({ c, r }, w, h, " Byte Code ");
|
Box myBox({ c, r }, w, h, " Byte Code ");
|
||||||
myBox.charset = BoxSet::DOUBLE;
|
myBox.charset = BoxSet::DOUBLE;
|
||||||
myBox.borderFg = color::GREEN;
|
myBox.borderFg = color::GREEN;
|
||||||
@@ -136,6 +214,20 @@ namespace spider {
|
|||||||
lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900);
|
lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawPanel() {
|
||||||
|
Terminal& t = *term;
|
||||||
|
t
|
||||||
|
<< pos(46, 3) << color::B_YELLOW << cyclesRan
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawValues() {
|
||||||
|
drawPanel();
|
||||||
|
drawCPUValues();
|
||||||
|
drawRAMValues();
|
||||||
|
drawByteCodeValues();
|
||||||
|
}
|
||||||
|
|
||||||
void drawFaceplate() {
|
void drawFaceplate() {
|
||||||
Terminal& t = *term;
|
Terminal& t = *term;
|
||||||
t
|
t
|
||||||
@@ -164,7 +256,7 @@ namespace spider {
|
|||||||
drawCPUFace();
|
drawCPUFace();
|
||||||
drawRAMFace();
|
drawRAMFace();
|
||||||
drawByteCodeFace();
|
drawByteCodeFace();
|
||||||
t << pos(101, 1) << color::YELLOW;
|
t << pos(104, 1) << color::YELLOW;
|
||||||
for(int i = 0; i < 47; i++) t << "═";
|
for(int i = 0; i < 47; i++) t << "═";
|
||||||
t << "╗";
|
t << "╗";
|
||||||
for(int i = 0; i < 5; i++) {
|
for(int i = 0; i < 5; i++) {
|
||||||
@@ -182,7 +274,7 @@ namespace spider {
|
|||||||
<< pos(29, 6) << color::B_BLACK << "[ MENU ]"
|
<< pos(29, 6) << color::B_BLACK << "[ MENU ]"
|
||||||
<< pos(4, 8) << color::CYAN << " CPU "
|
<< pos(4, 8) << color::CYAN << " CPU "
|
||||||
<< pos(40, 8) << color::RED << " RAM "
|
<< pos(40, 8) << color::RED << " RAM "
|
||||||
<< pos(81, 8) << color::GREEN << " Byte Code "
|
<< pos(82, 8) << color::GREEN << " Byte Code "
|
||||||
;
|
;
|
||||||
switch(mainMenuID) {
|
switch(mainMenuID) {
|
||||||
case 0x1: // step
|
case 0x1: // step
|
||||||
@@ -208,7 +300,7 @@ namespace spider {
|
|||||||
else t << "> RAM <";
|
else t << "> RAM <";
|
||||||
break;
|
break;
|
||||||
case 0x13: // instr
|
case 0x13: // instr
|
||||||
t << pos(81, 8) << color::GREEN << style::BOLD;
|
t << pos(82, 8) << color::GREEN << style::BOLD;
|
||||||
if(menuSelected) t << "[ Byte Code ]";
|
if(menuSelected) t << "[ Byte Code ]";
|
||||||
else t << "> Byte Code <";
|
else t << "> Byte Code <";
|
||||||
break;
|
break;
|
||||||
|
|||||||
+144
-3
@@ -1,18 +1,30 @@
|
|||||||
#include "LiveDebug.hpp"
|
#include "LiveDebug.hpp"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
// Resources //
|
// Resources //
|
||||||
|
Runtime runtime;
|
||||||
|
InstrReelDyn reel(256);
|
||||||
|
|
||||||
Terminal* term;
|
Terminal* term;
|
||||||
MenuMap* mainmenu;
|
MenuMap* mainmenu;
|
||||||
|
|
||||||
|
RamContent* ram_content;
|
||||||
|
InnerScroll* ram_scroll;
|
||||||
|
|
||||||
|
ByteCodeContent reel_content;
|
||||||
|
InnerScroll* reel_scroll;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
int mainMenuID = 1;
|
int mainMenuID = 1;
|
||||||
int intrMenuID = 1;
|
int intrMenuID = 1;
|
||||||
|
|
||||||
bool menuSelected = false;
|
bool menuSelected = false;
|
||||||
|
bool updateRAM = true;
|
||||||
|
bool updateReel = true;
|
||||||
int selCPUReg = 0;
|
int selCPUReg = 0;
|
||||||
int selRamPos = 0;
|
int selRamPos = 0;
|
||||||
int selInstrPos = 0;
|
int selInstrPos = 0;
|
||||||
@@ -30,6 +42,7 @@ namespace spider {
|
|||||||
.fill(backg::BLACK)
|
.fill(backg::BLACK)
|
||||||
;
|
;
|
||||||
drawFaceplate();
|
drawFaceplate();
|
||||||
|
drawValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Live Actions //
|
// Live Actions //
|
||||||
@@ -49,6 +62,12 @@ namespace spider {
|
|||||||
// Setup & Loop //
|
// Setup & Loop //
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
runtime.ram.resize(1024);
|
||||||
|
runtime.hookReel(&reel);
|
||||||
|
ram_content = new RamContent(&runtime.ram);
|
||||||
|
ram_scroll = new InnerScroll(pos(38, 9), 39, 29, *ram_content);
|
||||||
|
reel_scroll = new InnerScroll(pos(80, 9), 71, 29, reel_content);
|
||||||
|
|
||||||
clearAll();
|
clearAll();
|
||||||
mainmenu = new MenuMap(3, 5);
|
mainmenu = new MenuMap(3, 5);
|
||||||
mainmenu->setWrap(true, false);
|
mainmenu->setWrap(true, false);
|
||||||
@@ -63,6 +82,26 @@ namespace spider {
|
|||||||
mainmenu->fill(2, 4, 1, 3, 0x13);
|
mainmenu->fill(2, 4, 1, 3, 0x13);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an action according to the
|
||||||
|
* currently selected action on the panel.
|
||||||
|
* AKA: STEP, RUN, STOP, MENU
|
||||||
|
*/
|
||||||
|
void panelAction() {
|
||||||
|
switch(mainMenuID) {
|
||||||
|
case 1: // STEP
|
||||||
|
//runtime.step();
|
||||||
|
cyclesRan++;
|
||||||
|
break;
|
||||||
|
case 2: // RUN
|
||||||
|
break;
|
||||||
|
case 3: // STOP
|
||||||
|
break;
|
||||||
|
case 4: // MENU
|
||||||
|
break; // TODO: DO THIS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mainMenuCtrls(int k) {
|
void mainMenuCtrls(int k) {
|
||||||
switch(k) {
|
switch(k) {
|
||||||
case key::UP:
|
case key::UP:
|
||||||
@@ -77,6 +116,27 @@ namespace spider {
|
|||||||
case key::RIGHT:
|
case key::RIGHT:
|
||||||
mainmenu->moveRight();
|
mainmenu->moveRight();
|
||||||
break;
|
break;
|
||||||
|
case key::ENTER:
|
||||||
|
// This is a panel action
|
||||||
|
if(mainMenuID < 0x10) {
|
||||||
|
panelAction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// starting action, asap as it's
|
||||||
|
// selected. Usually just update
|
||||||
|
// the menu so it comes alive.
|
||||||
|
menuSelected = mainMenuID;
|
||||||
|
switch(mainMenuID) {
|
||||||
|
case 0x11:
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
updateRAM = true;
|
||||||
|
break;
|
||||||
|
case 0x13:
|
||||||
|
updateReel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -84,6 +144,77 @@ namespace spider {
|
|||||||
mainMenuID = r.id;
|
mainMenuID = r.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void selMenuCtrls(int k) {
|
||||||
|
switch(mainMenuID) {
|
||||||
|
case 0x11: // CPU
|
||||||
|
break;
|
||||||
|
case 0x12: // RAM
|
||||||
|
if(k == key::UP) {
|
||||||
|
ram_scroll->scroll(-1);
|
||||||
|
updateRAM = true;
|
||||||
|
}
|
||||||
|
if(k == key::DOWN) {
|
||||||
|
ram_scroll->scroll(1);
|
||||||
|
updateRAM = true;
|
||||||
|
}
|
||||||
|
if(k == 'q') updateRAM = true;
|
||||||
|
break;
|
||||||
|
case 0x13: // INSTR
|
||||||
|
if(k == key::UP) {
|
||||||
|
reel_scroll->scroll(-1);
|
||||||
|
reel_content.ipY = u64(reel_scroll->rowY);
|
||||||
|
reel_content.input.cancel();
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(k == key::DOWN) {
|
||||||
|
reel_scroll->scroll(1);
|
||||||
|
reel_content.ipY = u64(reel_scroll->rowY);
|
||||||
|
reel_content.input.cancel();
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(k == key::LEFT) {
|
||||||
|
reel_content.ipX = (reel_content.ipX - 1) % 16;
|
||||||
|
reel_content.input.cancel();
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(k == key::RIGHT) {
|
||||||
|
reel_content.ipX = (reel_content.ipX + 1) % 16;
|
||||||
|
reel_content.input.cancel();
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(std::isxdigit(k)) {
|
||||||
|
// Input enable.
|
||||||
|
// Clamp if outside of range.
|
||||||
|
u64 maxIP = reel.size();
|
||||||
|
u64 ip = std::min<u64>(reel_content.ipX + reel_content.ipY * 16, maxIP);
|
||||||
|
reel_content.ipX = ip % 16;
|
||||||
|
reel_content.ipY = ip / 16;
|
||||||
|
auto& t = *term;
|
||||||
|
t << pos(0, 0) << ip << ", " << maxIP;
|
||||||
|
reel_content.input.accept(char(k));
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(k == key::ENTER || reel_content.input.isComplete()) {
|
||||||
|
// Input enable.
|
||||||
|
// Clamp if outside of range.
|
||||||
|
u64 maxIP = reel.size();
|
||||||
|
u64 ip = std::min<u64>(reel_content.ipX + reel_content.ipY * 16, maxIP);
|
||||||
|
reel_content.ipX = ip % 16;
|
||||||
|
reel_content.ipY = ip / 16;
|
||||||
|
u8 byte = u8(reel_content.input.getValue());
|
||||||
|
reel.write(ip, &byte, 1);
|
||||||
|
reel_content.input.cancel();
|
||||||
|
updateReel = true;
|
||||||
|
}
|
||||||
|
if(k == 'q') updateReel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(k == 'q') {
|
||||||
|
menuSelected = false;
|
||||||
|
drawMainMenuSel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// time @79
|
// time @79
|
||||||
Terminal& t = *term;
|
Terminal& t = *term;
|
||||||
@@ -95,11 +226,21 @@ namespace spider {
|
|||||||
running = false;
|
running = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mainMenuCtrls(k);
|
|
||||||
drawMainMenuSel();
|
// if nothing selected, draw the main menu
|
||||||
|
// selection AND handle input
|
||||||
|
if(!menuSelected) {
|
||||||
|
mainMenuCtrls(k);
|
||||||
|
drawMainMenuSel();
|
||||||
|
} else { // inner, selected menu
|
||||||
|
selMenuCtrls(k);
|
||||||
|
}
|
||||||
|
drawValues();
|
||||||
|
|
||||||
// Favour the thread doing other stuff
|
// Favour the thread doing other stuff
|
||||||
if(!runVM) { // IF the vm is not continously running
|
if(runVM) { // IF the vm is not continously running
|
||||||
|
std::this_thread::yield();
|
||||||
|
} else {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,43 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <spider/runtime/Runtime.hpp>
|
#include <spider/runtime/Runtime.hpp>
|
||||||
|
#include <spider/runtime/reel/InstrReelDyn.hpp>
|
||||||
|
|
||||||
#include <desktoplib/terminal/Terminal.hpp>
|
#include <desktoplib/terminal/Terminal.hpp>
|
||||||
#include <desktoplib/terminal/ui/Box.hpp>
|
#include <desktoplib/terminal/ui/Box.hpp>
|
||||||
#include <desktoplib/terminal/ui/MenuMap.hpp>
|
#include <desktoplib/terminal/ui/MenuMap.hpp>
|
||||||
|
#include <desktoplib/terminal/ui/Content.hpp>
|
||||||
|
#include <desktoplib/terminal/ui/InnerScroll.hpp>
|
||||||
|
|
||||||
|
#include "RamContent.hpp"
|
||||||
|
#include "ByteCodeContent.hpp"
|
||||||
|
|
||||||
namespace spider {
|
namespace spider {
|
||||||
|
|
||||||
using namespace ckitty::terminal;
|
using namespace ckitty::terminal;
|
||||||
|
|
||||||
|
// Virtual Machine
|
||||||
|
extern Runtime runtime;
|
||||||
|
extern InstrReelDyn reel;
|
||||||
|
|
||||||
// Resources //
|
// Resources //
|
||||||
extern Terminal* term;
|
extern Terminal* term;
|
||||||
extern MenuMap* mainmenu;
|
extern MenuMap* mainmenu;
|
||||||
|
|
||||||
|
extern RamContent* ram_content;
|
||||||
|
extern InnerScroll* ram_scroll;
|
||||||
|
|
||||||
|
extern ByteCodeContent reel_content;
|
||||||
|
extern InnerScroll* reel_scroll;
|
||||||
|
|
||||||
extern bool running;
|
extern bool running;
|
||||||
extern int mainMenuID;
|
extern int mainMenuID;
|
||||||
extern bool menuSelected;
|
extern bool menuSelected;
|
||||||
|
extern bool updateRAM;
|
||||||
|
extern bool updateReel;
|
||||||
|
|
||||||
|
extern u64 cyclesRan;
|
||||||
|
extern bool runVM;
|
||||||
|
|
||||||
// UI Actions //
|
// UI Actions //
|
||||||
|
|
||||||
@@ -23,8 +45,14 @@ namespace spider {
|
|||||||
|
|
||||||
void drawFaceplate();
|
void drawFaceplate();
|
||||||
|
|
||||||
|
void drawValues();
|
||||||
|
|
||||||
void drawMainMenuSel();
|
void drawMainMenuSel();
|
||||||
|
|
||||||
|
void drawU64(u64 n);
|
||||||
|
|
||||||
|
void drawU8(u8 n);
|
||||||
|
|
||||||
std::string getTime();
|
std::string getTime();
|
||||||
|
|
||||||
// Live Actions //
|
// Live Actions //
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#include "RamContent.hpp"
|
||||||
|
#include "LiveDebug.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
RamContent::RamContent(RAM* _ram) : ram(_ram) {}
|
||||||
|
|
||||||
|
RamContent::~RamContent() {}
|
||||||
|
|
||||||
|
// Content must report how tall it wants to be
|
||||||
|
int RamContent::getTotalHeight() const {
|
||||||
|
return int(std::ceil(float(ram->size()) / 8.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render only the rows between startRow and endRow
|
||||||
|
// relativeY is where the Content starts drawing in terminal space
|
||||||
|
void RamContent::render(Terminal& t, pos screenPos, pos viewport, std::pair<int, int> rows) const {
|
||||||
|
// FF FF FF FF FF FF FF FF | XXXX XXXX #//
|
||||||
|
const u64 ram_size = ram->size();
|
||||||
|
char ascii[8];
|
||||||
|
|
||||||
|
for (int row = rows.first; row < rows.second; ++row) {
|
||||||
|
// Set terminal cursor position for the start of this row
|
||||||
|
t << pos(screenPos.x + 1, screenPos.y + (row - rows.first));
|
||||||
|
|
||||||
|
// Is this the selected column?
|
||||||
|
if(ram_scroll->rowY == row && menuSelected && mainMenuID == 0x12) {
|
||||||
|
t << backg::RED << color::WHITE;
|
||||||
|
} else {
|
||||||
|
t << style::RESET << color::WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Group 1: First 4 bytes ---
|
||||||
|
for (int col = 0; col < 4; ++col) {
|
||||||
|
u64 offset = static_cast<u64>(row * 8 + col);
|
||||||
|
if (offset < ram_size) {
|
||||||
|
u8 byte = ram->at(offset);
|
||||||
|
drawU8(byte);
|
||||||
|
ascii[col] = (byte >= 32 && byte <= 126) ? static_cast<char>(byte) : '.';
|
||||||
|
} else {
|
||||||
|
t << " ";
|
||||||
|
ascii[col] = ' ';
|
||||||
|
}
|
||||||
|
t << ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
t << ' ';
|
||||||
|
|
||||||
|
// --- Group 2: Next 4 bytes ---
|
||||||
|
for (int col = 4; col < 8; ++col) {
|
||||||
|
u64 offset = static_cast<u64>(row * 8 + col);
|
||||||
|
if (offset < ram_size) {
|
||||||
|
u8 byte = ram->at(offset);
|
||||||
|
drawU8(byte);
|
||||||
|
ascii[col] = (byte >= 32 && byte <= 126) ? static_cast<char>(byte) : '.';
|
||||||
|
} else {
|
||||||
|
t << " ";
|
||||||
|
ascii[col] = ' ';
|
||||||
|
}
|
||||||
|
t << " ";
|
||||||
|
}
|
||||||
|
t << color::B_BLACK;
|
||||||
|
t << "| ";
|
||||||
|
t << color::WHITE;
|
||||||
|
|
||||||
|
// --- ASCII Output Loop ---
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
t << ascii[i];
|
||||||
|
if (i == 3) t << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <spider/runtime/memory/RAM.hpp>
|
||||||
|
#include <desktoplib/terminal/ui/Content.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
using namespace ckitty::terminal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a specific part of the RAM.
|
||||||
|
*/
|
||||||
|
class RamContent : public Content {
|
||||||
|
public:
|
||||||
|
|
||||||
|
RAM* ram;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
RamContent(RAM* _ram);
|
||||||
|
|
||||||
|
virtual ~RamContent();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Content must report how tall it wants to be
|
||||||
|
virtual int getTotalHeight() const override;
|
||||||
|
|
||||||
|
// Render only the rows between startRow and endRow
|
||||||
|
// relativeY is where the Content starts drawing in terminal space
|
||||||
|
virtual void render(Terminal& t, pos screenPos, pos viewport, std::pair<int, int> rows) const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user