#include "SharedMemoryAccess.hpp" #include "internal.hpp" #include "vkvm.hpp" #include #include namespace vkvm { auto initialize(int pid) -> void { impl.sharedMemoryPid = pid; impl.sharedMemoryKey = 12345; impl.sharedMemorySize = 8000; initSemaphore(); setDefaultValues(); } 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]; 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()) { impl.eventTable[sig - SIGUSR1](); } } }); unlockSharedMemory(); return true; } } unlockSharedMemory(); return false; } auto setPixel(int x, int y, Color color) -> bool { 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) { case Text: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); if (color == reg->foreground_color) { //set bit to 1 ptr[0] |= (1 << (pixelIndex % bitsPerPixel)); } else { //set bit to 0 ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel)); } break; } case TwoColors: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); if (color.getRed() > 127 || color.getGreen() > 127 || color.getBlue() > 127) { //set bit to 1 ptr[0] |= (1 << (pixelIndex % bitsPerPixel)); } else { //set bit to 0 ptr[0] &= ~(1 << (pixelIndex % bitsPerPixel)); } break; } case Gray_256: { unsigned char *ptr = reinterpret_cast(getPixelArea()) + (y * getWidth() + x); int avg = color.getRed() + color.getGreen() + color.getBlue(); avg /= 3; ptr[0] = avg; break; } case RGB: { unsigned char *ptr = reinterpret_cast(getPixelArea()) + (y * getWidth() + x) * 3; ptr[0] = color.getRed(); ptr[1] = color.getGreen(); ptr[2] = color.getBlue(); break; } } //unlockSharedMemory(); return true; } auto getPixel(int x, int y) -> Color { 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) { 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) { color = reg->foreground_color; } else { color = reg->background_color; } break; } case TwoColors: { int pixelIndex = (y * getWidth() + x); unsigned char *ptr = reinterpret_cast(getPixelArea()) + (pixelIndex / bitsPerPixel); bool bit = static_cast(ptr[0] & (1 << (pixelIndex % bitsPerPixel))); if (bit) { color = reg->foreground_color; } else { color = reg->background_color; } break; } case Gray_256: { unsigned char *ptr = reinterpret_cast(getPixelArea()) + (y * getWidth() + x) * 1; color = {ptr[0], ptr[0], ptr[0]}; break; } case RGB: { unsigned char *ptr = reinterpret_cast(getPixelArea()) + (y * getWidth() + x) * 3; color = {ptr[0], ptr[1], ptr[2]}; break; } } return color; } auto setText(std::string text) -> bool { lockSharedMemory(); char *ptr = getTextArea(); for (int i = 0; i < static_cast(text.size()); i++) { if (i < getCharactersPerColumn() * getCharactersPerRow()) { ptr[i] = text[i]; } } if (text.size() < getCharactersPerColumn() * getCharactersPerRow()) { ptr[text.size()] = '\0'; } unlockSharedMemory(); callEvent(EventType::RenderText); return true; } auto getText() -> std::string { 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 { return static_cast(getRegisters()->layout_version); } auto reset() -> void { impl.sharedMemory = nullptr; impl.localSharedMemory.clear(); setDefaultValues(); } auto getWidth() -> int { return getRegisters()->width_pixels; } auto setWidth(int newValue) -> void { lockSharedMemory(); getRegisters()->width_pixels = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getHeight() -> int { return getRegisters()->height_pixels; } auto setHeight(int newValue) -> void { lockSharedMemory(); getRegisters()->height_pixels = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getMode() -> GraphicMode { return getRegisters()->graphicMode; } auto setMode(GraphicMode newValue) -> void { lockSharedMemory(); auto reg = getRegisters(); 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); } } 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]); } } lockSharedMemory(); } else { reg->graphicMode = newValue; } unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getRedrawInterval() -> int { return getRegisters()->autoRedrawInterval; } auto setRedrawInterval(int newValue) -> void { lockSharedMemory(); getRegisters()->autoRedrawInterval = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getTimerInterruptInterval() -> int { return getRegisters()->timerInterruptInterval; } auto setTimerInterruptInterval(int newValue) -> void { lockSharedMemory(); getRegisters()->timerInterruptInterval = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getBackgroundColor() -> Color { return getRegisters()->background_color; } auto setBackgroundColor(const Color &newValue) -> void { lockSharedMemory(); getRegisters()->background_color = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getForegroundColor() -> Color { return getRegisters()->foreground_color; } auto setForegroundColor(const Color &newValue) -> void { lockSharedMemory(); getRegisters()->foreground_color = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getCharactersPerRow() -> int { return getRegisters()->characters_per_row; } auto getCharactersPerColumn() -> int { return getRegisters()->characters_per_column; } auto getFont() -> FontType { return FontType(getRegisters()->textMode_font); } auto setFont(const FontType &newValue) -> void { lockSharedMemory(); getRegisters()->textMode_font = newValue; unlockSharedMemory(); callEvent(EventType::UpdateControlRegisters); } auto getMousePosition() -> Coordinates { return {getRegisters()->mouse_pos_x, getRegisters()->mouse_pos_y}; } auto getLastPressedKey() -> KeyCode { lockSharedMemory(); auto keyCode = KeyCode(0); auto reg = getRegisters(); 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; } }