diff --git a/.clang-tidy b/.clang-tidy index f404c2e..11c1ab7 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,3 +1,3 @@ -Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type' +Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers' WarningsAsErrors: 'true' HeaderFilterRegex: '.*,-catch.hpp' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 1554107..1e7c069 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,4 +39,13 @@ target_link_libraries(UnitTests Catch2::Catch2) include(CTest) include(Catch) -catch_discover_tests(UnitTests) \ No newline at end of file +catch_discover_tests(UnitTests) + +if (ENABLE_COVERAGE) + set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../external/codecov/cmake" ${CMAKE_MODULE_PATH}) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") + find_package(codecov) + add_coverage(UnitTests) + list(APPEND LCOV_REMOVE_PATTERNS "/usr/") + coverage_evaluate() +endif() diff --git a/src/Color.cpp b/src/Color.cpp index 8f03829..8b9629d 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -2,16 +2,21 @@ namespace vkvm { + constexpr int maxValue = 255; + Color::Color() noexcept : red(0), green(0), blue(0) {} - Color::Color(unsigned char red, unsigned char green, unsigned char blue) noexcept - : red(red), green(green), blue(blue) {} + Color::Color(int red, int green, int blue) noexcept { + setRed(red); + setGreen(green); + setBlue(blue); + } Color::Color(unsigned int hex) noexcept { - red = (unsigned char) ((hex >> 16 & 0xFF));//NOLINT - green = (unsigned char) ((hex >> 8u & 0xFF));//NOLINT - blue = (unsigned char) ((hex & 0xFF));//NOLINT + red = static_cast(hex >> 16 & 0xFF); + green = static_cast(hex >> 8U & 0xFF); + blue = static_cast((hex & 0xFF)); } auto Color::getRed() -> unsigned char { @@ -26,15 +31,27 @@ namespace vkvm { return blue; } - auto Color::setRed(unsigned char value) -> void { + auto Color::setRed(int value) -> void { + if(value > maxValue) { + value = maxValue; + } + red = value; } - auto Color::setGreen(unsigned char value) -> void { + auto Color::setGreen(int value) -> void { + if(value > maxValue) { + value = maxValue; + } + green = value; } - auto Color::setBlue(unsigned char value) -> void { + auto Color::setBlue(int value) -> void { + if(value > maxValue) { + value = maxValue; + } + blue = value; } diff --git a/src/Color.hpp b/src/Color.hpp index 8b3cc99..29c379e 100644 --- a/src/Color.hpp +++ b/src/Color.hpp @@ -18,7 +18,7 @@ namespace vkvm { public: Color() noexcept; - Color(unsigned char red, unsigned char green, unsigned char blue) noexcept; + Color(int red, int green, int blue) noexcept; explicit Color(unsigned int hex) noexcept; @@ -28,11 +28,11 @@ namespace vkvm { auto getBlue() -> unsigned char; - auto setRed(unsigned char value) -> void; + auto setRed(int value) -> void; - auto setGreen(unsigned char value) -> void; + auto setGreen(int value) -> void; - auto setBlue(unsigned char value) -> void; + auto setBlue(int value) -> void; bool operator==(const Color &other) const ; diff --git a/src/FontType.cpp b/src/FontType.cpp deleted file mode 100644 index 5e69054..0000000 --- a/src/FontType.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "FontType.hpp" - -namespace vkvm { - - FontType::FontType(int id, const char * name, int height, int width) noexcept : id(id), name(name), height(height), width(width) { - } - - auto FontType::getId() const -> int { - return id; - } - - auto FontType::getName() const -> std::string { - return std::string(name); - } - - auto FontType::getHeight() const -> int { - return height; - } - - auto FontType::getWidth() const -> int { - return width; - } - -} \ No newline at end of file diff --git a/src/FontType.hpp b/src/FontType.hpp index 349abd1..cff32e1 100644 --- a/src/FontType.hpp +++ b/src/FontType.hpp @@ -2,32 +2,15 @@ #define LIBRARY_FONT_H -#include -#include - namespace vkvm { - class FontType { - private: - int id; - const char * name; - int height; - int width; - - public: - FontType(int id, const char * name, int height, int width) noexcept; - - auto getId() const -> int; - - auto getName() const -> std::string; - - auto getHeight() const -> int; - - auto getWidth() const -> int; - + enum FontType { + FuturisticBlack = 1, + //TODO(julian): find name of this font + NoNameFound = 2, + ProFontIIX = 3, + Unifont = 4 }; - - static const FontType font_1 = FontType(1, "DummyFont", 10, 5); } #endif diff --git a/src/KeyCode.hpp b/src/KeyCode.hpp index d09dfdb..c618e7c 100644 --- a/src/KeyCode.hpp +++ b/src/KeyCode.hpp @@ -1,14 +1,17 @@ #ifndef LIBRARY_KEYCODE_HPP #define LIBRARY_KEYCODE_HPP -#include namespace vkvm { enum KeyCode { - Backspcce = 32, + Backspace = 32, Tab = 33, Enter = 37, + Arrow_Left = 105, + Arrow_Down = 108, + Arrow_Right = 107, + Arrow_Up = 106, ShiftLeft = 249, ShiftRight = 249, Ctrl = 251, diff --git a/src/SharedMemoryAccess.cpp b/src/SharedMemoryAccess.cpp index 57392e3..d129346 100644 --- a/src/SharedMemoryAccess.cpp +++ b/src/SharedMemoryAccess.cpp @@ -1,30 +1,24 @@ #include -#include #include -#include #include #include #include #include #include -#include -#include "SharedMemoryAccess.hpp" /* header is important for the shmID. name could be different. maybe not needed cause: (shmget(memory_access_key, NULL, 0)) */ +#include "SharedMemoryAccess.hpp" #include "internal.hpp" #include "log.hpp" namespace vkvm { - constexpr int PERM = 0666; /* access rights */ + constexpr int PERMISSION = 0666; constexpr int LOCK = -1; constexpr int UNLOCK = 1; constexpr int SEM_KEY = 123458L; -//int memoryAccessKey; /* var type is int. but could be another type. */ //TODO: look after type in sharedmemory group int semId; struct sembuf semaphore; - std::vector localSharedMemory; - auto initSemaphore() -> int { /* Testen, ob das Semaphor bereits existiert */ semId = semget(SEM_KEY, 0, IPC_PRIVATE); @@ -33,7 +27,7 @@ namespace vkvm { /* Alle Zugriffsrechte der Dateikreierungsmaske */ /* erlauben */ umask(0); - semId = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | PERM); + semId = semget(SEM_KEY, 1, IPC_CREAT | IPC_EXCL | PERMISSION); if (semId < 0) { return -1; } @@ -50,6 +44,7 @@ namespace vkvm { semaphore.sem_flg = SEM_UNDO; if (semop(semId, &semaphore, 1) == -1) { perror(" semop "); + log(LogLevel::CRITICAL, "could not operate on semaphore, exiting"); return -1; } return 1; @@ -67,11 +62,11 @@ namespace vkvm { givenWarning = true; log(LogLevel::WARNING, "no shared memory found, using local memory instead!"); } - if (localSharedMemory.empty()) { + if (impl.localSharedMemory.empty()) { constexpr int kilo = 1024; - localSharedMemory.resize(impl.sharedMemorySize * kilo); + impl.localSharedMemory.resize(impl.sharedMemorySize * kilo); } - return &localSharedMemory[0]; + return &impl.localSharedMemory[0]; } auto getSharedMemory() -> char * { @@ -90,6 +85,7 @@ namespace vkvm { impl.sharedMemory = ptr; return ptr; } + //using a local buffer for shared memory testing return getLocalMemory(); } diff --git a/src/internal.cpp b/src/internal.cpp index 436c76e..a889c4a 100644 --- a/src/internal.cpp +++ b/src/internal.cpp @@ -8,6 +8,26 @@ namespace vkvm { Impl impl; + auto setDefaultValues() -> void { + impl.localMemoryWarn = false; + if (getSharedMemory() != nullptr) { + if(getSharedMemory() == &impl.localSharedMemory[0]) { + setMode(GraphicMode::RGB); + setCharactersPerRow(60); + setCharactersPerColumn(20); + setHeight(600); + setWidth(800); + setMousePosition(42, 42); + setBackgroundColor(black); + setForegroundColor(white); + setRedrawInterval(500); + setTimerInterruptInterval(1000); + setFont(FontType::ProFontIIX); + } + } + impl.localMemoryWarn = true; + } + auto sendSignal(pid_t pid, int signalNumber) -> void { kill(pid, signalNumber); } @@ -50,18 +70,21 @@ namespace vkvm { lockSharedMemory(); getRegisters()->layout_version = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto setCharactersPerColumn(int newValue) -> void { lockSharedMemory(); getRegisters()->characters_per_column = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto setCharactersPerRow(int newValue) -> void { lockSharedMemory(); getRegisters()->characters_per_row = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto setMousePosition(int x, int y) -> void { @@ -69,16 +92,26 @@ namespace vkvm { getRegisters()->mouse_pos_x = x; getRegisters()->mouse_pos_y = y; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto buttonPressed(KeyCode keyCode) -> void { lockSharedMemory(); auto reg = getRegisters(); - if (reg->keyboardBuffer_index_write >= sizeof(reg->keyboardBuffer)) { - reg->keyboardBuffer_index_write = 0; - } - reg->keyboardBuffer[reg->keyboardBuffer_index_write++] = keyCode; + reg->keyboardBuffer[(reg->keyboardBuffer_index_write) % keyboardBufferSize] = keyCode; unlockSharedMemory(); } + auto getRegisteredProcesses(EventType eventType) -> std::vector { + std::vector result; + auto ivt = getInterruptTable(); + for(int i = 0; i < impl.interruptEntrysPerEventType;i++){ + auto &entry= ivt[eventType * impl.interruptEntrysPerEventType + i]; + if (entry.pid != 0) { + result.push_back(entry.pid); + } + } + return result; + } + } diff --git a/src/internal.hpp b/src/internal.hpp index e1b5ea2..8eb6826 100644 --- a/src/internal.hpp +++ b/src/internal.hpp @@ -38,7 +38,7 @@ constexpr int keyboardBufferSize = 16; int textMode_font_height; int mouse_pos_x; int mouse_pos_y; - std::array keyboardBuffer; + std::array keyboardBuffer; int keyboardBuffer_index_write; int keyboardBuffer_index_read; }; @@ -61,10 +61,14 @@ constexpr int keyboardBufferSize = 16; std::vector> eventTable; bool localMemoryWarn = true; char *sharedMemory = nullptr; + std::vector localSharedMemory; }; extern Impl impl; + + auto setDefaultValues() -> void; + /** * send a signal to a process * @param pid of the process to which the signal is send @@ -126,6 +130,12 @@ constexpr int keyboardBufferSize = 16; */ auto buttonPressed(KeyCode keyCode) -> void; +/** + * get registered Processes for a given event type. + * @param eventType. + */ + auto getRegisteredProcesses(EventType eventType) -> std::vector; + // Shared Memory Layout // -------------------------------------------------------------------- // struct ControlRegisters diff --git a/src/log.cpp b/src/log.cpp index c015f84..d7999c0 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -5,9 +5,15 @@ */ #include "log.hpp" +#include #include namespace vkvm { + + LogLevel logLevel = LogLevel::INFO; + LogLevel fileLogLevel = LogLevel::INFO; + std::ofstream logToFileStream;//NOLINT + //converts the level to a string of the level auto getLevelName(LogLevel level) -> std::string { switch(level){ @@ -44,66 +50,98 @@ namespace vkvm { } } - LogLevel logLevel = LogLevel::INFO; - //log the current time - auto logTime() -> void { + auto logTime() -> std::string { time_t rawtime; time(&rawtime); struct tm *timeinfo; timeinfo = localtime(&rawtime); - constexpr int decimalBase = 10; + std::stringstream stream; if (timeinfo->tm_hour < decimalBase) { - std::cout << "0"; + stream << "0"; } - std::cout << timeinfo->tm_hour; - std::cout << ":"; + stream << timeinfo->tm_hour; + stream << ":"; if (timeinfo->tm_min < decimalBase) { - std::cout << "0"; + stream << "0"; } - std::cout << timeinfo->tm_min; - std::cout << ":"; + stream << timeinfo->tm_min; + stream << ":"; if (timeinfo->tm_sec < decimalBase) { - std::cout << "0"; + stream << "0"; } - std::cout << timeinfo->tm_sec; + stream << timeinfo->tm_sec; + return stream.str(); } //log the message auto log(LogLevel level, const std::string &msg) -> void { - if(level >= logLevel) { + if(level >= logLevel || level >= fileLogLevel) { std::string levelName = getLevelName(level); const int maxLevelNameLength = 8; - //time - std::cout << "["; - logTime(); - std::cout << "] "; + std::stringstream stream; + std::stringstream noColorStream; - //color and level name;lo - std::cout << "["; - std::cout << "\033[" << getLevelColor(level) << "m" << levelName << "\033[0m"; - std::cout << "] "; + //time + std::string time = logTime(); + stream << "["; + stream << time; + stream << "] "; + + noColorStream << "["; + noColorStream << time; + noColorStream << "] "; + + //color and level name + stream << "["; + stream << "\033[" << getLevelColor(level) << "m" << levelName << "\033[0m"; + stream << "] "; for (int i = levelName.size(); i < maxLevelNameLength; i++) { - std::cout << " "; + stream << " "; } + //no color and level name + noColorStream << "["; + noColorStream << levelName; + noColorStream << "] "; + for (int i = levelName.size(); i < maxLevelNameLength; i++) { + noColorStream << " "; + } + + + //message for(char c : msg){ if(c == '\n'){ //intend newlines so that they align with the start of the message - std::cout << "\n"; + stream << "\n"; + noColorStream << "\n"; const int paddingSize = 22; for(int i = 0; i < paddingSize;i++){ - std::cout << " "; + stream << " "; + noColorStream << " "; } }else{ - std::cout << c; + stream << c; + noColorStream << c; + } + } + stream << "\n"; + noColorStream << "\n"; + + if(level >= logLevel){ + std::cout << stream.str(); + } + if(logToFileStream.is_open()){ + if(level >= fileLogLevel){ + logToFileStream << noColorStream.str(); + //TODO(julian): fixme + logToFileStream.flush(); } } - std::cout << "\n"; } } @@ -111,4 +149,17 @@ namespace vkvm { logLevel = level; } + auto setLogFileLevel(LogLevel level) -> void { + fileLogLevel = level; + } + + auto setLogToFile(const std::string &file) -> void { + if(logToFileStream.is_open()){ + logToFileStream.close(); + } + if(!file.empty()){ + logToFileStream.open(file, std::ofstream::app); + } + } + } diff --git a/src/log.hpp b/src/log.hpp index 8d80990..1b40ad0 100644 --- a/src/log.hpp +++ b/src/log.hpp @@ -47,6 +47,8 @@ namespace vkvm { * @since 0.1.0 */ auto setLogLevel(LogLevel level) -> void; + auto setLogFileLevel(LogLevel level) -> void; + auto setLogToFile(const std::string &file) -> void; } #endif diff --git a/src/vkvm.cpp b/src/vkvm.cpp index df48721..5c03457 100644 --- a/src/vkvm.cpp +++ b/src/vkvm.cpp @@ -6,51 +6,32 @@ #include namespace vkvm { - // NOLINT + auto initialize(int pid) -> void { impl.sharedMemoryPid = pid; - impl.sharedMemoryKey = 12345;// NOLINT - impl.sharedMemorySize = 8000;// NOLINT + impl.sharedMemoryKey = 12345; + impl.sharedMemorySize = 8000; initSemaphore(); setDefaultValues(); } - auto setDefaultValues() -> void { - impl.localMemoryWarn = false; - if(getSharedMemory() != nullptr) { - //set default values - setMode(GraphicMode::RGB); - setCharactersPerRow(60);// NOLINT - setCharactersPerColumn(20);// NOLINT - setHeight(600);// NOLINT - setWidth(800);// NOLINT - setMousePosition(42, 42);// NOLINT - setBackgroundColor(black); - setForegroundColor(white); - setRedrawInterval(20);// NOLINT - setTimerInterruptInterval(10);// NOLINT - setFont(FontType(3,"",0,0)); - } - impl.localMemoryWarn = true; - } - auto registerEvent(EventType type, const std::function &handler) -> bool { int signum = SIGUSR1 + impl.eventTable.size(); auto ivt = getInterruptTable(); lockSharedMemory(); - for(int i = 0; i < impl.interruptEntrysPerEventType;i++){ - auto &entry= ivt[type * impl.interruptEntrysPerEventType + i]; + for (int i = 0; i < impl.interruptEntrysPerEventType; i++) { + auto &entry = ivt[type * impl.interruptEntrysPerEventType + i]; if (entry.pid == 0) { entry.pid = getpid(); entry.signum = signum; impl.eventTable.push_back(handler); - onSignal(signum, [](int sig){ - if(sig >= SIGUSR1){ - if((sig - SIGUSR1) < impl.eventTable.size()){ + onSignal(signum, [](int sig) { + if (sig >= SIGUSR1) { + if ((sig - SIGUSR1) < impl.eventTable.size()) { impl.eventTable[sig - SIGUSR1](); } } @@ -64,19 +45,24 @@ namespace vkvm { } auto setPixel(int x, int y, Color color) -> bool { - lockSharedMemory(); + if(x < 0 || y < 0){ + return false; + } + if (x > getWidth() || y > getHeight()) { + return false; + } + //lockSharedMemory(); auto reg = getRegisters(); const int bitsPerPixel = 8; - switch(reg->graphicMode) { + switch (reg->graphicMode) { case Text: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); - if(color == reg->foreground_color){ + if (color == reg->foreground_color) { //set bit to 1 ptr[0] |= (1 << (pixelIndex % bitsPerPixel)); - } - else{ + } else { //set bit to 0 ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel)); } @@ -85,11 +71,10 @@ namespace vkvm { case TwoColors: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); - if(color == reg->foreground_color){ + if (color.getRed() > 127 || color.getGreen() > 127 || color.getBlue() > 127) { //set bit to 1 ptr[0] |= (1 << (pixelIndex % bitsPerPixel)); - } - else{ + } else { //set bit to 0 ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel)); } @@ -110,24 +95,31 @@ namespace vkvm { break; } } - unlockSharedMemory(); - return false; + //unlockSharedMemory(); + return true; } auto getPixel(int x, int y) -> Color { - Color color = Color(0,0,0); + if(x < 0 || y < 0) { + return getBackgroundColor(); + } + if (x > getWidth() || y > getHeight()) { + return getBackgroundColor(); + } + + Color color = Color(0, 0, 0); auto reg = getRegisters(); const int bitsPerPixel = 8; - switch(reg->graphicMode) { + switch (reg->graphicMode) { case Text: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + pixelIndex / bitsPerPixel; bool bit = static_cast(ptr[0] & (1 << (pixelIndex % bitsPerPixel))); - if(bit){ + if (bit) { color = reg->foreground_color; - }else{ - color =reg->background_color; + } else { + color = reg->background_color; } break; } @@ -135,10 +127,10 @@ namespace vkvm { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); bool bit = static_cast(ptr[0] & (1 << (pixelIndex % bitsPerPixel))); - if(bit){ + if (bit) { color = reg->foreground_color; - }else{ - color =reg->background_color; + } else { + color = reg->background_color; } break; } @@ -159,21 +151,35 @@ namespace vkvm { auto setText(std::string text) -> bool { lockSharedMemory(); char *ptr = getTextArea(); - for(int i = 0; i < static_cast(text.size());i++){ - if(i >= getCharactersPerColumn() * getCharactersPerRow()){ - break; + for (int i = 0; i < static_cast(text.size()); i++) { + if (i < getCharactersPerColumn() * getCharactersPerRow()) { + ptr[i] = text[i]; } - ptr[i] = text[i]; } - if(text.size() < getCharactersPerColumn() * getCharactersPerRow()){ + if (text.size() < getCharactersPerColumn() * getCharactersPerRow()) { ptr[text.size()] = '\0'; } unlockSharedMemory(); + callEvent(EventType::RenderText); return true; } auto getText() -> std::string { - return std::string (getTextArea()); + std::string text = getTextArea(); + + return text.substr(0, getCharactersPerColumn() * getCharactersPerRow()); + } + + auto clearText() -> bool { + lockSharedMemory(); + char *ptr = getTextArea(); + for (int i = 0; i < getCharactersPerColumn() * getCharactersPerRow(); ++i) { + ptr[i] = '\0'; + } + + unlockSharedMemory(); + callEvent(EventType::RenderText); + return true; } auto getLayoutVersion() -> LayoutVersion { @@ -181,7 +187,7 @@ namespace vkvm { } auto reset() -> void { - //TODO(julian): reset + setDefaultValues(); } auto getWidth() -> int { @@ -192,6 +198,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->width_pixels = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getHeight() -> int { @@ -202,6 +209,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->height_pixels = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getMode() -> GraphicMode { @@ -211,32 +219,33 @@ namespace vkvm { auto setMode(GraphicMode newValue) -> void { lockSharedMemory(); auto reg = getRegisters(); - if(reg->graphicMode != newValue){ + if (reg->graphicMode != newValue) { std::vector pixels; int height = reg->height_pixels; int width = reg->width_pixels; pixels.resize(height * width); - for(int y = 0; y < height;y++){ - for(int x = 0;x < width;x++){ - pixels[y * width + x] = getPixel(x,y); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + pixels[y * width + x] = getPixel(x, y); } } getRegisters()->graphicMode = newValue; unlockSharedMemory(); - for(int y = 0; y < height;y++){ - for(int x = 0;x < width;x++){ - setPixel(x,y, pixels[y * width + x]); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + setPixel(x, y, pixels[y * width + x]); } } lockSharedMemory(); - }else{ + } else { reg->graphicMode = newValue; } unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getRedrawInterval() -> int { @@ -247,6 +256,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->autoRedrawInterval = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getTimerInterruptInterval() -> int { @@ -257,6 +267,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->timerInterruptInterval = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getBackgroundColor() -> Color { @@ -267,6 +278,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->background_color = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getForegroundColor() -> Color { @@ -277,6 +289,7 @@ namespace vkvm { lockSharedMemory(); getRegisters()->foreground_color = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getCharactersPerRow() -> int { @@ -288,15 +301,14 @@ namespace vkvm { } auto getFont() -> FontType { - //TODO(julian): get font properly - return {getRegisters()->textMode_font, "", 0, 0}; + return FontType(getRegisters()->textMode_font); } auto setFont(const FontType &newValue) -> void { - //TODO(julian): setFont properly lockSharedMemory(); - getRegisters()->textMode_font = newValue.getId(); + getRegisters()->textMode_font = newValue; unlockSharedMemory(); + callEvent(EventType::UpdateControlRegisters); } auto getMousePosition() -> Coordinates { @@ -307,12 +319,15 @@ namespace vkvm { lockSharedMemory(); auto keyCode = KeyCode(0); auto reg = getRegisters(); - if(reg->keyboardBuffer_index_read != reg->keyboardBuffer_index_write) { - keyCode = static_cast(reg->keyboardBuffer[reg->keyboardBuffer_index_read++]); - if (reg->keyboardBuffer_index_read >= sizeof(reg->keyboardBuffer)) { - reg->keyboardBuffer_index_read = 0; - } + + if(reg->keyboardBuffer_index_read >= reg->keyboardBuffer_index_write) { + auto code = reg->keyboardBuffer[(reg->keyboardBuffer_index_read) % keyboardBufferSize]; + keyCode = KeyCode(code); + }else{ + auto code = reg->keyboardBuffer[(reg->keyboardBuffer_index_read) % keyboardBufferSize]; + keyCode = KeyCode(code); } + unlockSharedMemory(); return keyCode; } diff --git a/src/vkvm.hpp b/src/vkvm.hpp index ed70601..7c50541 100644 --- a/src/vkvm.hpp +++ b/src/vkvm.hpp @@ -28,7 +28,6 @@ namespace vkvm { */ auto initialize(int pid) -> void; - auto setDefaultValues() -> void; /** * set pixel at a x,y position to a certain color. @@ -67,6 +66,13 @@ namespace vkvm { */ auto getText() -> std::string; + /** + * clear text area + * @return if text could be cleared, false if it could not be cleared. + */ + auto clearText() -> bool; + + //Control registers start here //all modes diff --git a/test/area_test.cpp b/test/area_test.cpp new file mode 100644 index 0000000..3306598 --- /dev/null +++ b/test/area_test.cpp @@ -0,0 +1,25 @@ +#include "../src/vkvm.hpp" +#include + +TEST_CASE("AREA") { + vkvm::initialize(0); + vkvm::setWidth(200); + vkvm::setHeight(200); + + SECTION("inside bounds") { + REQUIRE(vkvm::setPixel(100, 100, vkvm::white)); + REQUIRE(vkvm::getPixel(100, 100) == vkvm::white); + } + + SECTION("Out of bounds") { + REQUIRE_FALSE(vkvm::setPixel(400, 400, vkvm::white)); + REQUIRE(vkvm::getPixel(400, 400) == vkvm::black); + + REQUIRE_FALSE(vkvm::setPixel(-5, -5, vkvm::white)); + REQUIRE(vkvm::getPixel(-5, -5) == vkvm::black); + + vkvm::setBackgroundColor(vkvm::blue); + + REQUIRE(vkvm::getPixel(400, 400) == vkvm::blue); + } +} \ No newline at end of file diff --git a/test/buffer_test.cpp b/test/buffer_test.cpp new file mode 100644 index 0000000..979d058 --- /dev/null +++ b/test/buffer_test.cpp @@ -0,0 +1,19 @@ +#include "../src/internal.hpp" +#include "../src/vkvm.hpp" +#include + + +TEST_CASE("Keyboard Buffer") { + SECTION("write") { + vkvm::setLogLevel(vkvm::DEBUG); + //vkvm::buttonPressed(vkvm::A); + //vkvm::buttonPressed(vkvm::B); + //vkvm::buttonPressed(vkvm::C); + } + + SECTION("read") { + //CHECK(vkvm::getLastPressedKey() == vkvm::C); + //CHECK(vkvm::getLastPressedKey() == vkvm::C); + //CHECK(vkvm::getLastPressedKey() == vkvm::C); + } +} \ No newline at end of file diff --git a/test/color_test.cpp b/test/color_test.cpp index 32154ff..ffd8703 100644 --- a/test/color_test.cpp +++ b/test/color_test.cpp @@ -4,45 +4,72 @@ TEST_CASE("Colors") { vkvm::initialize(0); - vkvm::setPixel(10, 10, vkvm::black);//NOLINT - vkvm::setPixel(11, 11, vkvm::white);//NOLINT - vkvm::setPixel(12, 12, vkvm::green);//NOLINT - vkvm::setPixel(13, 13, vkvm::red);//NOLINT - vkvm::setPixel(14, 14, vkvm::blue);//NOLINT - vkvm::setPixel(15, 15, vkvm::Color(66, 77, 88)); //NOLINT - vkvm::setPixel(16, 16, vkvm::Color(0xFFFFFF));//NOLINT + vkvm::setMode(vkvm::RGB); + REQUIRE(vkvm::setPixel(10, 10, vkvm::black)); + REQUIRE(vkvm::setPixel(11, 11, vkvm::white)); + REQUIRE(vkvm::setPixel(12, 12, vkvm::green)); + REQUIRE(vkvm::setPixel(13, 13, vkvm::red)); + REQUIRE(vkvm::setPixel(14, 14, vkvm::blue)); + REQUIRE(vkvm::setPixel(15, 15, vkvm::Color(66, 77, 88))); + REQUIRE(vkvm::setPixel(16, 16, vkvm::Color(0xFFFFFF))); + REQUIRE(vkvm::setPixel(17, 17, vkvm::Color(500, 500, 500))); + REQUIRE(vkvm::setPixel(18, 18, vkvm::Color(0x000000))); SECTION("RGB") { - REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT - REQUIRE(vkvm::getPixel(12, 12) == vkvm::green);//NOLINT - REQUIRE(vkvm::getPixel(13, 13) == vkvm::red);//NOLINT - REQUIRE(vkvm::getPixel(14, 14) == vkvm::blue);//NOLINT - REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(66, 77, 88));//NOLINT - REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT + REQUIRE(vkvm::getPixel(10, 10) == vkvm::black); + REQUIRE(vkvm::getPixel(11, 11) == vkvm::white); + REQUIRE(vkvm::getPixel(12, 12) == vkvm::green); + REQUIRE(vkvm::getPixel(13, 13) == vkvm::red); + REQUIRE(vkvm::getPixel(14, 14) == vkvm::blue); + REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(66, 77, 88)); + REQUIRE(vkvm::getPixel(16, 16) == vkvm::white); + REQUIRE(vkvm::getPixel(17, 17) == vkvm::white); + REQUIRE(vkvm::getPixel(18, 18) == vkvm::black); } SECTION("TwoColors") { vkvm::setMode(vkvm::TwoColors); - REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT - REQUIRE(vkvm::getPixel(12, 12) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(13, 13) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(14, 14) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(15, 15) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT + REQUIRE(vkvm::getPixel(10, 10) == vkvm::black); + REQUIRE(vkvm::getPixel(11, 11) == vkvm::white); + REQUIRE(vkvm::getPixel(12, 12) == vkvm::white); + REQUIRE(vkvm::getPixel(13, 13) == vkvm::white); + REQUIRE(vkvm::getPixel(14, 14) == vkvm::white); + REQUIRE(vkvm::getPixel(15, 15) == vkvm::black); + REQUIRE(vkvm::getPixel(16, 16) == vkvm::white); + REQUIRE(vkvm::getPixel(17, 17) == vkvm::white); + REQUIRE(vkvm::getPixel(18, 18) == vkvm::black); + + + //different foreground/background color + vkvm::setBackgroundColor(vkvm::blue); + vkvm::setForegroundColor(vkvm::red); + + REQUIRE(vkvm::getBackgroundColor() == vkvm::blue); + REQUIRE(vkvm::getForegroundColor() == vkvm::red); + + REQUIRE(vkvm::getPixel(10, 10) == vkvm::blue); + REQUIRE(vkvm::getPixel(11, 11) == vkvm::red); + REQUIRE(vkvm::getPixel(12, 12) == vkvm::red); + REQUIRE(vkvm::getPixel(13, 13) == vkvm::red); + REQUIRE(vkvm::getPixel(14, 14) == vkvm::red); + REQUIRE(vkvm::getPixel(15, 15) == vkvm::blue); + REQUIRE(vkvm::getPixel(16, 16) == vkvm::red); + REQUIRE(vkvm::getPixel(17, 17) == vkvm::red); + REQUIRE(vkvm::getPixel(18, 18) == vkvm::blue); } SECTION("Gray256") { vkvm::setMode(vkvm::Gray_256); - REQUIRE(vkvm::getPixel(10, 10) == vkvm::black);//NOLINT - REQUIRE(vkvm::getPixel(11, 11) == vkvm::white);//NOLINT - REQUIRE(vkvm::getPixel(12, 12) == vkvm::Color(85, 85, 85));//NOLINT - REQUIRE(vkvm::getPixel(13, 13) == vkvm::Color(85, 85, 85));//NOLINT - REQUIRE(vkvm::getPixel(14, 14) == vkvm::Color(85, 85, 85));//NOLINT - REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(77, 77, 77));//NOLINT - REQUIRE(vkvm::getPixel(16, 16) == vkvm::white);//NOLINT + REQUIRE(vkvm::getPixel(10, 10) == vkvm::black); + REQUIRE(vkvm::getPixel(11, 11) == vkvm::white); + REQUIRE(vkvm::getPixel(12, 12) == vkvm::Color(85, 85, 85)); + REQUIRE(vkvm::getPixel(13, 13) == vkvm::Color(85, 85, 85)); + REQUIRE(vkvm::getPixel(14, 14) == vkvm::Color(85, 85, 85)); + REQUIRE(vkvm::getPixel(15, 15) == vkvm::Color(77, 77, 77)); + REQUIRE(vkvm::getPixel(16, 16) == vkvm::white); + REQUIRE(vkvm::getPixel(17, 17) == vkvm::white); + REQUIRE(vkvm::getPixel(18, 18) == vkvm::black); } } diff --git a/test/default_test.cpp b/test/default_test.cpp new file mode 100644 index 0000000..a5ca01e --- /dev/null +++ b/test/default_test.cpp @@ -0,0 +1,70 @@ +#include "../src/internal.hpp" +#include "../src/vkvm.hpp" +#include + +TEST_CASE("Default values") { + vkvm::initialize(0); + + SECTION("before") { + REQUIRE(vkvm::getMode() == vkvm::RGB); + REQUIRE(vkvm::getCharactersPerRow() == 60); + REQUIRE(vkvm::getCharactersPerColumn() == 20); + REQUIRE(vkvm::getHeight() == 600); + REQUIRE(vkvm::getWidth() == 800); + REQUIRE(vkvm::getMousePosition().x == 42); + REQUIRE(vkvm::getMousePosition().y == 42); + REQUIRE(vkvm::getBackgroundColor() == vkvm::black); + REQUIRE(vkvm::getForegroundColor() == vkvm::white); + REQUIRE(vkvm::getRedrawInterval() == 500); + REQUIRE(vkvm::getTimerInterruptInterval() == 1000); + REQUIRE(vkvm::getFont() == vkvm::ProFontIIX); + } + + SECTION("change") { + vkvm::setMode(vkvm::TwoColors); + vkvm::setCharactersPerRow(100); + vkvm::setCharactersPerColumn(100); + vkvm::setHeight(40); + vkvm::setWidth(40); + vkvm::setMousePosition(41, 43); + vkvm::setBackgroundColor(vkvm::red); + vkvm::setForegroundColor(vkvm::blue); + vkvm::setRedrawInterval(1); + vkvm::setTimerInterruptInterval(2); + vkvm::setFont(vkvm::ProFontIIX); + + + + REQUIRE(vkvm::getMode() == vkvm::TwoColors); + REQUIRE(vkvm::getCharactersPerRow() == 100); + REQUIRE(vkvm::getCharactersPerColumn() == 100); + REQUIRE(vkvm::getHeight() == 40); + REQUIRE(vkvm::getWidth() == 40); + REQUIRE(vkvm::getMousePosition().x == 41); + REQUIRE(vkvm::getMousePosition().y == 43); + REQUIRE(vkvm::getBackgroundColor() == vkvm::red); + REQUIRE(vkvm::getForegroundColor() == vkvm::blue); + REQUIRE(vkvm::getRedrawInterval() == 1); + REQUIRE(vkvm::getTimerInterruptInterval() == 2); + REQUIRE(vkvm::getFont() == vkvm::ProFontIIX); + } + + + SECTION("after") { + vkvm::reset(); + REQUIRE(vkvm::getMode() == vkvm::RGB); + REQUIRE(vkvm::getCharactersPerRow() == 60); + REQUIRE(vkvm::getCharactersPerColumn() == 20); + REQUIRE(vkvm::getHeight() == 600); + REQUIRE(vkvm::getWidth() == 800); + REQUIRE(vkvm::getMousePosition().x == 42); + REQUIRE(vkvm::getMousePosition().y == 42); + REQUIRE(vkvm::getBackgroundColor() == vkvm::black); + REQUIRE(vkvm::getForegroundColor() == vkvm::white); + REQUIRE(vkvm::getRedrawInterval() == 500); + REQUIRE(vkvm::getTimerInterruptInterval() == 1000); + REQUIRE(vkvm::getFont() == vkvm::ProFontIIX); + + } + +} diff --git a/test/event_test.cpp b/test/event_test.cpp new file mode 100644 index 0000000..64275c1 --- /dev/null +++ b/test/event_test.cpp @@ -0,0 +1,32 @@ +#include "../src/internal.hpp" +#include "../src/vkvm.hpp" +#include + +TEST_CASE("Event") { + vkvm::initialize(0); + + SECTION("Register") { + bool mouseMove = false; + bool keyup = false; + bool keyup2 = false; + vkvm::registerEvent(vkvm::MouseMove, [&]() { + mouseMove = true; + }); + vkvm::registerEvent(vkvm::KeyUp, [&]() { + keyup = true; + }); + vkvm::registerEvent(vkvm::KeyUp, [&]() { + keyup2 = true; + }); + + REQUIRE_FALSE(mouseMove); + vkvm::callEvent(vkvm::MouseMove); + REQUIRE(mouseMove); + + REQUIRE_FALSE(keyup); + REQUIRE_FALSE(keyup2); + vkvm::callEvent(vkvm::KeyUp); + REQUIRE(keyup); + REQUIRE(keyup2); + } +} diff --git a/test/public_test.cpp b/test/public_test.cpp deleted file mode 100644 index 05f9467..0000000 --- a/test/public_test.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "catch2/catch.hpp" -#include "../src/vkvm.hpp" - -TEST_CASE("add works") { - vkvm::initialize(0); - vkvm::setText("Hello World"); - SECTION("equals") { - REQUIRE(vkvm::getText() == "Hello World"); - } -} \ No newline at end of file diff --git a/test/text_test.cpp b/test/text_test.cpp new file mode 100644 index 0000000..8996f16 --- /dev/null +++ b/test/text_test.cpp @@ -0,0 +1,28 @@ +#include "../src/internal.hpp" +#include "../src/vkvm.hpp" +#include + +TEST_CASE("Text") { + vkvm::initialize(0); + + REQUIRE(vkvm::setText("Hello World, this is a test")); + REQUIRE(vkvm::getText() == "Hello World, this is a test"); + + REQUIRE(vkvm::setText("Hello World")); + REQUIRE(vkvm::getText() == "Hello World"); + + vkvm::setCharactersPerColumn(5); + vkvm::setCharactersPerRow(1); + + REQUIRE(vkvm::clearText()); + + REQUIRE(vkvm::getCharactersPerColumn() == 5); + REQUIRE(vkvm::getCharactersPerRow() == 1); + + REQUIRE(vkvm::setText("Hello World")); + REQUIRE(vkvm::getText() == "Hello"); + + REQUIRE(vkvm::clearText()); + + REQUIRE(vkvm::getText().empty()); +} \ No newline at end of file