#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 setDefaultValues() -> void { impl.localMemoryWarn = false; if(getSharedMemory() != nullptr) { //set default values setMode(GraphicMode::RGB); setCharactersPerRow(60); setCharactersPerColumn(20); setHeight(600); setWidth(800); setMousePosition(42, 42); setBackgroundColor(black); setForegroundColor(white); setRedrawInterval(20); setTimerInterruptInterval(10); 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]; 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 > 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 == reg->foreground_color){ //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 > 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()){ break; } ptr[i] = text[i]; } if(text.size() < getCharactersPerColumn() * getCharactersPerRow()){ ptr[text.size()] = '\0'; } unlockSharedMemory(); return true; } auto getText() -> std::string { return std::string (getTextArea()); } auto getLayoutVersion() -> LayoutVersion { return static_cast(getRegisters()->layout_version); } auto reset() -> void { //TODO(julian): reset } auto getWidth() -> int { return getRegisters()->width_pixels; } auto setWidth(int newValue) -> void { lockSharedMemory(); getRegisters()->width_pixels = newValue; unlockSharedMemory(); } auto getHeight() -> int { return getRegisters()->height_pixels; } auto setHeight(int newValue) -> void { lockSharedMemory(); getRegisters()->height_pixels = newValue; unlockSharedMemory(); } 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(); } auto getRedrawInterval() -> int { return getRegisters()->autoRedrawInterval; } auto setRedrawInterval(int newValue) -> void { lockSharedMemory(); getRegisters()->autoRedrawInterval = newValue; unlockSharedMemory(); } auto getTimerInterruptInterval() -> int { return getRegisters()->timerInterruptInterval; } auto setTimerInterruptInterval(int newValue) -> void { lockSharedMemory(); getRegisters()->timerInterruptInterval = newValue; unlockSharedMemory(); } auto getBackgroundColor() -> Color { return getRegisters()->background_color; } auto setBackgroundColor(const Color &newValue) -> void { lockSharedMemory(); getRegisters()->background_color = newValue; unlockSharedMemory(); } auto getForegroundColor() -> Color { return getRegisters()->foreground_color; } auto setForegroundColor(const Color &newValue) -> void { lockSharedMemory(); getRegisters()->foreground_color = newValue; unlockSharedMemory(); } auto getCharactersPerRow() -> int { return getRegisters()->characters_per_row; } auto getCharactersPerColumn() -> int { return getRegisters()->characters_per_column; } auto getFont() -> FontType { //TODO(julian): get font properly return {getRegisters()->textMode_font, "", 0, 0}; } auto setFont(const FontType &newValue) -> void { //TODO(julian): setFont properly lockSharedMemory(); getRegisters()->textMode_font = newValue.getId(); unlockSharedMemory(); } 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) { keyCode = static_cast(reg->keyboardBuffer[reg->keyboardBuffer_index_read++]); if (reg->keyboardBuffer_index_read >= sizeof(reg->keyboardBuffer)) { reg->keyboardBuffer_index_read = 0; } } unlockSharedMemory(); return keyCode; } }