#include #include #include #include #include #include #include "console.h" #include "gen.h" #include "utils.h" console::console(std::atomic_bool *const terminate, std::atomic_bool *const interrupt_emulation, bus *const b) : terminate(terminate), interrupt_emulation(interrupt_emulation), b(b) { memset(screen_buffer, ' ', sizeof screen_buffer); } console::~console() { } void console::start_thread() { stop_thread_flag = false; #if !defined(ESP32) th = new std::thread(std::ref(*this)); #endif } void console::stop_thread() { if (th) { stop_thread_flag = true; th->join(); delete th; th = nullptr; } } bool console::poll_char() { std::unique_lock lck(input_lock); return input_buffer.empty() == false; } int console::get_char() { std::unique_lock lck(input_lock); if (input_buffer.empty()) return -1; char c = input_buffer.at(0); input_buffer.erase(input_buffer.begin() + 0); return c; } int console::wait_char(const int timeout_ms) { std::unique_lock lck(input_lock); using namespace std::chrono_literals; if (input_buffer.empty() == false || have_data.wait_for(lck, timeout_ms * 1ms) == std::cv_status::no_timeout) { if (input_buffer.empty() == false) { int c = input_buffer.at(0); input_buffer.erase(input_buffer.begin() + 0); return c; } } return -1; } void console::flush_input() { input_buffer.clear(); } std::string console::read_line(const std::string & prompt) { put_string(prompt); put_string(">"); std::string str; for(;;) { char c = wait_char(500); if (*terminate || stop_thread_flag) return ""; if (c == -1) continue; if (c == 13 || c == 10) break; if (c == 8) { if (!str.empty()) { str = str.substr(0, str.size() - 1); put_char(8); put_char(' '); put_char(8); } } else if (c >= 32 && c < 127) { str += c; put_char(c); } } put_string_lf(""); return str; } void console::debug(const std::string fmt, ...) { char *buffer = nullptr; va_list ap; va_start(ap, fmt); vasprintf(&buffer, fmt.c_str(), ap); va_end(ap); put_string_lf(buffer); free(buffer); } void console::put_char(const char c) { put_char_ll(c); if (c == 0) { } else if (c == 13) tx = 0; else if (c == 10) ty++; else if (c == 8) { // backspace if (tx > 0) tx--; } else { screen_buffer[ty][tx++] = c; if (tx == t_width) { tx = 0; ty++; } } if (ty == t_height) { memmove(&screen_buffer[0], &screen_buffer[1], sizeof(char) * t_width * (t_height - 1)); ty--; memset(screen_buffer[t_height - 1], ' ', t_width); } } void console::put_string(const std::string & what) { for(size_t x=0; x