diff --git a/bastl/include/array b/bastl/include/array index f3bd822..dda1d47 100644 --- a/bastl/include/array +++ b/bastl/include/array @@ -25,7 +25,7 @@ public: using iterator = pointer; using const_iterator = const_pointer; - T _elements[N]; + T _elements[N] = {}; constexpr reference operator[](size_type pos) noexcept { diff --git a/bastl/include/cstdio b/bastl/include/cstdio index 639fc10..7cbc106 100644 --- a/bastl/include/cstdio +++ b/bastl/include/cstdio @@ -8,10 +8,19 @@ namespace std { +using ::EOF; + using ::putchar; using ::puts; using ::printf; using ::vprintf; +using ::snprintf; +using ::vsnprintf; + +using ::fgets; +using ::fgetc; +using ::getc; +using ::getchar; } #endif // !defined(BAD_APPLE_OS_CSTDIO_INCLUDED) diff --git a/targets/_any/include/drivers/ps2.hpp b/targets/_any/include/drivers/ps2.hpp index e9a957e..55e050e 100644 --- a/targets/_any/include/drivers/ps2.hpp +++ b/targets/_any/include/drivers/ps2.hpp @@ -4,6 +4,7 @@ #if !defined(BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED) #define BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED +#include #include "drivers/pic.hpp" namespace baos::ps2 @@ -77,6 +78,7 @@ enum class Scancode ENTER = 0x5A, BRACKET_CLOSE = 0x5B, BACKSLASH = 0x5D, + GRAVE = 0x61, BACKSPACE = 0x66, KP_1 = 0x69, KP_4 = 0x6B, @@ -98,46 +100,61 @@ enum class Scancode SCROLLOCK = 0x7E, F7 = 0x83, - MM_WWW_SEARCH = 0xE010, - RIGHT_ALT = 0xE011, - RIGHT_CONTROL = 0xE014, - MM_PREV_TRACK = 0xE015, - LEFT_GUI = 0xE01F, - MM_WWW_FAVORITES = 0xE020, - MM_VOLUME_DOWN = 0xE021, - MM_MUTE = 0xE023, - RIGHT_GUI = 0xE027, - MM_WWW_STOP = 0xE028, - MM_CALCULATOR = 0xE02B, - APPS = 0xE02F, - MM_WWW_FORWARD = 0xE030, - MM_VOLUME_UP = 0xE032, - MM_PLAY_PAUSE = 0xE034, - ACPI_POWER = 0xE037, - MM_WWW_BACK = 0xE038, - MM_WWW_HOME = 0xE03A, - MM_STOP = 0xE03B, - ACPI_SLEEP = 0xE03F, - MM_MY_COMPUTER = 0xE040, - MM_EMAIL = 0xE048, - KP_SLASH = 0xE04A, - MM_NEXT_TRACK = 0xE04D, - MM_MEDIA_SELECT = 0xE050, - KP_ENTER = 0xE05A, - ACPI_WAKE = 0xE05E, - END = 0xE069, - ARROW_LEFT = 0xE06B, - HOME = 0xE06C, - INSERT = 0xE070, - DELETE = 0xE071, - ARROW_DOWN = 0xE072, - ARROW_RIGHT = 0xE074, - ARROW_UP = 0xE075, - PAGE_DOWN = 0xE07A, - PAGE_UP = 0xE07D, + MM_WWW_SEARCH = 0x0110, + RIGHT_ALT = 0x0111, + RIGHT_CONTROL = 0x0114, + MM_PREV_TRACK = 0x0115, + LEFT_GUI = 0x011F, + MM_WWW_FAVORITES = 0x0120, + MM_VOLUME_DOWN = 0x0121, + MM_MUTE = 0x0123, + RIGHT_GUI = 0x0127, + MM_WWW_STOP = 0x0128, + MM_CALCULATOR = 0x012B, + APPS = 0x012F, + MM_WWW_FORWARD = 0x0130, + MM_VOLUME_UP = 0x0132, + MM_PLAY_PAUSE = 0x0134, + ACPI_POWER = 0x0137, + MM_WWW_BACK = 0x0138, + MM_WWW_HOME = 0x013A, + MM_STOP = 0x013B, + ACPI_SLEEP = 0x013F, + MM_MY_COMPUTER = 0x0140, + MM_EMAIL = 0x0148, + KP_SLASH = 0x014A, + MM_NEXT_TRACK = 0x014D, + MM_MEDIA_SELECT = 0x0150, + KP_ENTER = 0x015A, + ACPI_WAKE = 0x015E, + END = 0x0169, + ARROW_LEFT = 0x016B, + HOME = 0x016C, + INSERT = 0x0170, + DELETE = 0x0171, + ARROW_DOWN = 0x0172, + ARROW_RIGHT = 0x0174, + ARROW_UP = 0x0175, + PAGE_DOWN = 0x017A, + PAGE_UP = 0x017D, - PRINT_SCREEN = 0xF000, - PAUSE = 0xF001 + PRINT_SCREEN = 0x017E, + PAUSE = 0x017F +}; +inline constexpr std::uint16_t MAX_SCANCODE = static_cast(Scancode::PAUSE) + 1; + +struct Keymap +{ + std::array regularKeys; + std::array shiftedKeys; + std::array altGredKeys; + + constexpr void set(Scancode scancode, char regular, char shifted = '\0', char altgred = '\0') noexcept + { + regularKeys[static_cast(scancode)] = regular; + shiftedKeys[static_cast(scancode)] = shifted; + altGredKeys[static_cast(scancode)] = altgred; + } }; struct KeyEvent @@ -152,8 +169,11 @@ struct KeyEvent __attribute__((interrupt)) void isrKeyboard(InterruptFrame* interruptFrame) noexcept; +[[nodiscard]] bool isKeyDown(Scancode scancode) noexcept; [[nodiscard]] bool readKey(KeyEvent& outEvent) noexcept; +[[nodiscard]] bool readChar(char& outChar) noexcept; [[nodiscard]] const char* keyName(Scancode scancode) noexcept; +[[nodiscard]] bool keyToChar(Scancode scancode, char& outChar) noexcept; } #endif // !defined(BAD_APPLE_OS_DRIVERS_PS2_HPP_INCLUDED) diff --git a/targets/_any/include/os/tools/ringbuffer.hpp b/targets/_any/include/os/tools/ringbuffer.hpp new file mode 100644 index 0000000..8f4353b --- /dev/null +++ b/targets/_any/include/os/tools/ringbuffer.hpp @@ -0,0 +1,44 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED) +#define BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED + +#include +#include + +namespace baos +{ +template +class RingBuffer +{ +private: + std::array mElements; + std::size_t mBufferedElements = 0; + std::size_t mPosition = 0; +public: + [[nodiscard]] bool full() const noexcept { return mBufferedElements == SIZE; } + [[nodiscard]] bool empty() const noexcept { return mBufferedElements == 0; } + bool append(T element) noexcept + { + if (full()) { + return false; + } + mElements[mPosition] = std::move(element); + ++mBufferedElements; + mPosition = (mPosition + 1) % SIZE; + return true; + } + bool next(T& outElement) noexcept + { + if (empty()) { + return false; + } + outElement = std::move(mElements[(mPosition + SIZE - mBufferedElements) % SIZE]); + --mBufferedElements; + return true; + } +}; +} + +#endif // !defined(BAD_APPLE_OS_OS_TOOLS_RINGBUFFER_HPP_INCLUDED) diff --git a/targets/_any/include/stdio.h b/targets/_any/include/stdio.h index e9c0749..b26a9a8 100644 --- a/targets/_any/include/stdio.h +++ b/targets/_any/include/stdio.h @@ -8,8 +8,16 @@ #include #include "./detail/common.h" +#define stdin __stdin + BA_EXTERN_C_BEGIN +typedef struct __file FILE; + +extern FILE* __stdin; + +static int EOF = -1; + int putchar(int chr) BA_CXX_NOEXCEPT; int puts(const char* str) BA_CXX_NOEXCEPT; int printf(const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 1, 2))); @@ -17,6 +25,11 @@ int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT; int snprintf(char* buffer, size_t bufferSize, const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 3, 4))); int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist) BA_CXX_NOEXCEPT; +int fgetc(FILE* stream) BA_CXX_NOEXCEPT; +char* fgets(char* buffer, int count, FILE* stream) BA_CXX_NOEXCEPT; +inline int getc(FILE* stream) BA_CXX_NOEXCEPT { return fgetc(stream); } +inline int getchar() BA_CXX_NOEXCEPT { return fgetc(stdin); } + BA_EXTERN_C_END #endif // !defined(BAD_APPLE_OS_STDIO_H_INCLUDED) diff --git a/targets/_any/src/app/main.cpp b/targets/_any/src/app/main.cpp index a925b44..bc2a154 100644 --- a/targets/_any/src/app/main.cpp +++ b/targets/_any/src/app/main.cpp @@ -1,6 +1,16 @@ +#include + extern "C" void main() { + // __asm__ __volatile__("cli"); - while(true); + while(true) + { + int chr = std::getchar(); + if (chr != std::EOF) + { + putchar(chr); + } + } } diff --git a/targets/_any/src/cstdlib/stdio.cpp b/targets/_any/src/cstdlib/stdio.cpp index 360dd2b..118ed19 100644 --- a/targets/_any/src/cstdlib/stdio.cpp +++ b/targets/_any/src/cstdlib/stdio.cpp @@ -2,13 +2,37 @@ #include #include -#include -#include -#include #include +#include "drivers/ps2.hpp" #include "os/serial.hpp" #include "os/tty.hpp" #include "os/tools/printf_helper.hpp" +#include "os/tools/ringbuffer.hpp" + +struct __file +{ +protected: + static constexpr unsigned BUFFER_SIZE = 4096; + + baos::RingBuffer mBuffer; + bool mEof = false; + bool mError = false; +protected: + virtual bool underflow() noexcept = 0; +public: + [[nodiscard]] bool isEof() const noexcept { return mEof; } + [[nodiscard]] bool isError() const noexcept { return mError; } + + bool readChar(char& outChar) noexcept + { + while (!mBuffer.next(outChar)) { + if (!underflow()) { + return false; + } + } + return true; + } +}; namespace { @@ -34,10 +58,33 @@ struct BufferPrinter } } }; + +class StdinFile : public __file +{ +public: + bool underflow() noexcept override + { + while (mBuffer.empty()) + { + char chr; + while (!mBuffer.full() && baos::ps2::readChar(chr)) + { + mBuffer.append(chr); + if (chr == '\n') { + break; + } + } + } + return true; + } +}; +StdinFile gStdin; } extern "C" { +FILE* __stdin = &gStdin; + int putchar(int chr) noexcept { tty::putChar(static_cast(chr)); @@ -100,5 +147,42 @@ int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist } return length; } + +int fgetc(FILE* stream) noexcept +{ + char chr; + if (!stream->readChar(chr)) + { + return EOF; + } + return chr; +} + +char* fgets(char* buffer, int count, FILE* stream) noexcept +{ + if (count < 1) { + return nullptr; + } + if (count == 1) + { + *buffer = '\0'; + return buffer; + } + + int pos = 0; + for (; pos < count - 1; ++pos) + { + if (!stream->readChar(buffer[pos])) + { + if (stream->isError() || pos == 0) + { + return nullptr; + } + break; + } + } + buffer[pos] = '\0'; + return buffer; +} } // extern "C" diff --git a/targets/_any/src/drivers/ps2.cpp b/targets/_any/src/drivers/ps2.cpp index 3079f8e..57802c8 100644 --- a/targets/_any/src/drivers/ps2.cpp +++ b/targets/_any/src/drivers/ps2.cpp @@ -1,12 +1,296 @@ #include "drivers/ps2.hpp" -#include +#include #include "drivers/pic.hpp" #include "os/port.hpp" +namespace baos::ps2 +{ namespace { +// +const constinit Keymap KEYMAP_EN_US = []() +{ + Keymap keymap = {}; + keymap.set(Scancode::BACKTICK, '`', '~'); + keymap.set(Scancode::_0, '0', ')'); + keymap.set(Scancode::_1, '1', '!'); + keymap.set(Scancode::_2, '2', '@'); + keymap.set(Scancode::_3, '3', '#'); + keymap.set(Scancode::_4, '4', '$'); + keymap.set(Scancode::_5, '5', '%'); + keymap.set(Scancode::_6, '6', '^'); + keymap.set(Scancode::_7, '7', '&'); + keymap.set(Scancode::_8, '8', '*'); + keymap.set(Scancode::_9, '9', '('); + keymap.set(Scancode::A, 'a', 'A'); + keymap.set(Scancode::B, 'b', 'B'); + keymap.set(Scancode::C, 'c', 'C'); + keymap.set(Scancode::D, 'd', 'D'); + keymap.set(Scancode::E, 'e', 'E'); + keymap.set(Scancode::F, 'f', 'F'); + keymap.set(Scancode::G, 'g', 'G'); + keymap.set(Scancode::H, 'h', 'H'); + keymap.set(Scancode::I, 'i', 'I'); + keymap.set(Scancode::J, 'j', 'J'); + keymap.set(Scancode::K, 'k', 'K'); + keymap.set(Scancode::L, 'l', 'L'); + keymap.set(Scancode::M, 'm', 'M'); + keymap.set(Scancode::N, 'n', 'N'); + keymap.set(Scancode::O, 'o', 'O'); + keymap.set(Scancode::P, 'p', 'P'); + keymap.set(Scancode::Q, 'q', 'Q'); + keymap.set(Scancode::R, 'r', 'R'); + keymap.set(Scancode::S, 's', 'S'); + keymap.set(Scancode::T, 't', 'T'); + keymap.set(Scancode::U, 'u', 'U'); + keymap.set(Scancode::V, 'v', 'V'); + keymap.set(Scancode::W, 'w', 'W'); + keymap.set(Scancode::X, 'x', 'X'); + keymap.set(Scancode::Y, 'y', 'Y'); + keymap.set(Scancode::Z, 'z', 'Z'); + keymap.set(Scancode::ENTER, '\n'); + keymap.set(Scancode::MINUS, '-', '_'); + keymap.set(Scancode::EQUALS, '=', '+'); + keymap.set(Scancode::TAB, '\t'); + keymap.set(Scancode::BRACKET_OPEN, '[', '{'); + keymap.set(Scancode::BRACKET_CLOSE, ']', '}'); + keymap.set(Scancode::BACKSLASH, '\\', '|'); + keymap.set(Scancode::SEMICOLON, ';', ':'); + keymap.set(Scancode::APOSTROPHE, '\'', '"'); + keymap.set(Scancode::GRAVE, '`', '~'); + keymap.set(Scancode::COMMA, ',', '<'); + keymap.set(Scancode::DOT, '.', '>'); + keymap.set(Scancode::SLASH, '/', '?'); + + keymap.set(Scancode::KP_ENTER, '\n'); + keymap.set(Scancode::KP_0, '0'); + keymap.set(Scancode::KP_1, '1'); + keymap.set(Scancode::KP_2, '2'); + keymap.set(Scancode::KP_3, '3'); + keymap.set(Scancode::KP_4, '4'); + keymap.set(Scancode::KP_5, '5'); + keymap.set(Scancode::KP_6, '6'); + keymap.set(Scancode::KP_7, '7'); + keymap.set(Scancode::KP_8, '8'); + keymap.set(Scancode::KP_9, '9'); + keymap.set(Scancode::KP_SLASH, '/'); + keymap.set(Scancode::KP_ASTERISK, '*'); + keymap.set(Scancode::KP_MINUS, '-'); + keymap.set(Scancode::KP_PLUS, '+'); + return keymap; +}(); +// + +// +const constinit Keymap KEYMAP_DE_DE = []() +{ + Keymap keymap = {}; + keymap.set(Scancode::BACKTICK, '^' /*'°'*/); + keymap.set(Scancode::_0, '0', '=', '}'); + keymap.set(Scancode::_1, '1', '!'); + keymap.set(Scancode::_2, '2', '"'); + keymap.set(Scancode::_3, '3' /*'§'*/); + keymap.set(Scancode::_4, '4', '$'); + keymap.set(Scancode::_5, '5', '%'); + keymap.set(Scancode::_6, '6', '&'); + keymap.set(Scancode::_7, '7', '/', '{'); + keymap.set(Scancode::_8, '8', '(', '['); + keymap.set(Scancode::_9, '9', ')', ']'); + keymap.set(Scancode::A, 'a', 'A'); + keymap.set(Scancode::B, 'b', 'B'); + keymap.set(Scancode::C, 'c', 'C'); + keymap.set(Scancode::D, 'd', 'D'); + keymap.set(Scancode::E, 'e', 'E' /*, '€' */); + keymap.set(Scancode::F, 'f', 'F'); + keymap.set(Scancode::G, 'g', 'G'); + keymap.set(Scancode::H, 'h', 'H'); + keymap.set(Scancode::I, 'i', 'I'); + keymap.set(Scancode::J, 'j', 'J'); + keymap.set(Scancode::K, 'k', 'K'); + keymap.set(Scancode::L, 'l', 'L'); + keymap.set(Scancode::M, 'm', 'M'); + keymap.set(Scancode::N, 'n', 'N'); + keymap.set(Scancode::O, 'o', 'O'); + keymap.set(Scancode::P, 'p', 'P'); + keymap.set(Scancode::Q, 'q', 'Q', '@'); + keymap.set(Scancode::R, 'r', 'R'); + keymap.set(Scancode::S, 's', 'S'); + keymap.set(Scancode::T, 't', 'T'); + keymap.set(Scancode::U, 'u', 'U'); + keymap.set(Scancode::V, 'v', 'V'); + keymap.set(Scancode::W, 'w', 'W'); + keymap.set(Scancode::X, 'x', 'X'); + keymap.set(Scancode::Y, 'y', 'Y'); + keymap.set(Scancode::Z, 'z', 'Z'); + keymap.set(Scancode::ENTER, '\n'); + keymap.set(Scancode::MINUS, '?' /* ß */, '?', '\\'); + keymap.set(Scancode::EQUALS, '`' /* ´ */, '`'); + keymap.set(Scancode::TAB, '\t'); + // keymap.set(Scancode::BRACKET_OPEN, 'ü', 'Ü'); + keymap.set(Scancode::BRACKET_CLOSE, '+', '*', '~'); + // keymap.set(Scancode::BACKSLASH, '\\', '|'); + // keymap.set(Scancode::SEMICOLON, 'ö', 'Ö'); + // keymap.set(Scancode::APOSTROPHE, 'ä', 'Ä'); + keymap.set(Scancode::GRAVE, '<', '>', '|'); + keymap.set(Scancode::COMMA, ',', ';'); + keymap.set(Scancode::DOT, '.', ':'); + keymap.set(Scancode::SLASH, '-', '_'); + + keymap.set(Scancode::KP_ENTER, '\n'); + keymap.set(Scancode::KP_0, '0'); + keymap.set(Scancode::KP_1, '1'); + keymap.set(Scancode::KP_2, '2'); + keymap.set(Scancode::KP_3, '3'); + keymap.set(Scancode::KP_4, '4'); + keymap.set(Scancode::KP_5, '5'); + keymap.set(Scancode::KP_6, '6'); + keymap.set(Scancode::KP_7, '7'); + keymap.set(Scancode::KP_8, '8'); + keymap.set(Scancode::KP_9, '9'); + keymap.set(Scancode::KP_SLASH, '/'); + keymap.set(Scancode::KP_ASTERISK, '*'); + keymap.set(Scancode::KP_MINUS, '-'); + keymap.set(Scancode::KP_PLUS, '+'); + return keymap; +}(); +// + +// +const constinit std::array SCANCODE_NAMES = []() +{ + std::array names; + names.fill("INVALID"); + names[static_cast(Scancode::F9)] = "F9"; + names[static_cast(Scancode::F5)] = "F5"; + names[static_cast(Scancode::F3)] = "F3"; + names[static_cast(Scancode::F1)] = "F1"; + names[static_cast(Scancode::F2)] = "F2"; + names[static_cast(Scancode::F12)] = "F12"; + names[static_cast(Scancode::F10)] = "F10"; + names[static_cast(Scancode::F8)] = "F8"; + names[static_cast(Scancode::F6)] = "F6"; + names[static_cast(Scancode::F4)] = "F4"; + names[static_cast(Scancode::TAB)] = "TAB"; + names[static_cast(Scancode::BACKTICK)] = "BACKTICK"; + names[static_cast(Scancode::LEFT_ALT)] = "LEFT_ALT"; + names[static_cast(Scancode::LEFT_SHIFT)] = "LEFT_SHIFT"; + names[static_cast(Scancode::LEFT_CONTROL)] = "LEFT_CONTROL"; + names[static_cast(Scancode::Q)] = "Q"; + names[static_cast(Scancode::_1)] = "_1"; + names[static_cast(Scancode::Z)] = "Z"; + names[static_cast(Scancode::S)] = "S"; + names[static_cast(Scancode::A)] = "A"; + names[static_cast(Scancode::W)] = "W"; + names[static_cast(Scancode::_2)] = "_2"; + names[static_cast(Scancode::C)] = "C"; + names[static_cast(Scancode::X)] = "X"; + names[static_cast(Scancode::D)] = "D"; + names[static_cast(Scancode::E)] = "E"; + names[static_cast(Scancode::_4)] = "_4"; + names[static_cast(Scancode::_3)] = "_3"; + names[static_cast(Scancode::SPACE)] = "SPACE"; + names[static_cast(Scancode::V)] = "V"; + names[static_cast(Scancode::F)] = "F"; + names[static_cast(Scancode::T)] = "T"; + names[static_cast(Scancode::R)] = "R"; + names[static_cast(Scancode::_5)] = "_5"; + names[static_cast(Scancode::N)] = "N"; + names[static_cast(Scancode::B)] = "B"; + names[static_cast(Scancode::H)] = "H"; + names[static_cast(Scancode::G)] = "G"; + names[static_cast(Scancode::Y)] = "Y"; + names[static_cast(Scancode::_6)] = "_6"; + names[static_cast(Scancode::M)] = "M"; + names[static_cast(Scancode::J)] = "J"; + names[static_cast(Scancode::U)] = "U"; + names[static_cast(Scancode::_7)] = "_7"; + names[static_cast(Scancode::_8)] = "_8"; + names[static_cast(Scancode::COMMA)] = "COMMA"; + names[static_cast(Scancode::K)] = "K"; + names[static_cast(Scancode::I)] = "I"; + names[static_cast(Scancode::O)] = "O"; + names[static_cast(Scancode::_0)] = "_0"; + names[static_cast(Scancode::_9)] = "_9"; + names[static_cast(Scancode::DOT)] = "DOT"; + names[static_cast(Scancode::SLASH)] = "SLASH"; + names[static_cast(Scancode::L)] = "L"; + names[static_cast(Scancode::SEMICOLON)] = "SEMICOLON"; + names[static_cast(Scancode::P)] = "P"; + names[static_cast(Scancode::MINUS)] = "MINUS"; + names[static_cast(Scancode::APOSTROPHE)] = "APOSTROPHE"; + names[static_cast(Scancode::BRACKET_OPEN)] = "BRACKET_OPEN"; + names[static_cast(Scancode::EQUALS)] = "EQUALS"; + names[static_cast(Scancode::CAPSLOCK)] = "CAPSLOCK"; + names[static_cast(Scancode::RIGHT_SHIFT)] = "RIGHT_SHIFT"; + names[static_cast(Scancode::ENTER)] = "ENTER"; + names[static_cast(Scancode::BRACKET_CLOSE)] = "BRACKET_CLOSE"; + names[static_cast(Scancode::BACKSLASH)] = "BACKSLASH"; + names[static_cast(Scancode::GRAVE)] = "GRAVE"; + names[static_cast(Scancode::BACKSPACE)] = "BACKSPACE"; + names[static_cast(Scancode::KP_1)] = "KP_1"; + names[static_cast(Scancode::KP_4)] = "KP_4"; + names[static_cast(Scancode::KP_7)] = "KP_7"; + names[static_cast(Scancode::KP_0)] = "KP_0"; + names[static_cast(Scancode::KP_DOT)] = "KP_DOT"; + names[static_cast(Scancode::KP_2)] = "KP_2"; + names[static_cast(Scancode::KP_5)] = "KP_5"; + names[static_cast(Scancode::KP_6)] = "KP_6"; + names[static_cast(Scancode::KP_8)] = "KP_8"; + names[static_cast(Scancode::ESCAPE)] = "ESCAPE"; + names[static_cast(Scancode::NUMLOCK)] = "NUMLOCK"; + names[static_cast(Scancode::F11)] = "F11"; + names[static_cast(Scancode::KP_PLUS)] = "KP_PLUS"; + names[static_cast(Scancode::KP_3)] = "KP_3"; + names[static_cast(Scancode::KP_MINUS)] = "KP_MINUS"; + names[static_cast(Scancode::KP_ASTERISK)] = "KP_ASTERISK"; + names[static_cast(Scancode::KP_9)] = "KP_9"; + names[static_cast(Scancode::SCROLLOCK)] = "SCROLLOCK"; + names[static_cast(Scancode::F7)] = "F7"; + names[static_cast(Scancode::MM_WWW_SEARCH)] = "MM_WWW_SEARCH"; + names[static_cast(Scancode::RIGHT_ALT)] = "RIGHT_ALT"; + names[static_cast(Scancode::RIGHT_CONTROL)] = "RIGHT_CONTROL"; + names[static_cast(Scancode::MM_PREV_TRACK)] = "MM_PREV_TRACK"; + names[static_cast(Scancode::LEFT_GUI)] = "LEFT_GUI"; + names[static_cast(Scancode::MM_WWW_FAVORITES)] = "MM_WWW_FAVORITES"; + names[static_cast(Scancode::MM_VOLUME_DOWN)] = "MM_VOLUME_DOWN"; + names[static_cast(Scancode::MM_MUTE)] = "MM_MUTE"; + names[static_cast(Scancode::RIGHT_GUI)] = "RIGHT_GUI"; + names[static_cast(Scancode::MM_WWW_STOP)] = "MM_WWW_STOP"; + names[static_cast(Scancode::MM_CALCULATOR)] = "MM_CALCULATOR"; + names[static_cast(Scancode::APPS)] = "APPS"; + names[static_cast(Scancode::MM_WWW_FORWARD)] = "MM_WWW_FORWARD"; + names[static_cast(Scancode::MM_VOLUME_UP)] = "MM_VOLUME_UP"; + names[static_cast(Scancode::MM_PLAY_PAUSE)] = "MM_PLAY_PAUSE"; + names[static_cast(Scancode::ACPI_POWER)] = "ACPI_POWER"; + names[static_cast(Scancode::MM_WWW_BACK)] = "MM_WWW_BACK"; + names[static_cast(Scancode::MM_WWW_HOME)] = "MM_WWW_HOME"; + names[static_cast(Scancode::MM_STOP)] = "MM_STOP"; + names[static_cast(Scancode::ACPI_SLEEP)] = "ACPI_SLEEP"; + names[static_cast(Scancode::MM_MY_COMPUTER)] = "MM_MY_COMPUTER"; + names[static_cast(Scancode::MM_EMAIL)] = "MM_EMAIL"; + names[static_cast(Scancode::KP_SLASH)] = "KP_SLASH"; + names[static_cast(Scancode::MM_NEXT_TRACK)] = "MM_NEXT_TRACK"; + names[static_cast(Scancode::MM_MEDIA_SELECT)] = "MM_MEDIA_SELECT"; + names[static_cast(Scancode::KP_ENTER)] = "KP_ENTER"; + names[static_cast(Scancode::ACPI_WAKE)] = "ACPI_WAKE"; + names[static_cast(Scancode::END)] = "END"; + names[static_cast(Scancode::ARROW_LEFT)] = "ARROW_LEFT"; + names[static_cast(Scancode::HOME)] = "HOME"; + names[static_cast(Scancode::INSERT)] = "INSERT"; + names[static_cast(Scancode::DELETE)] = "DELETE"; + names[static_cast(Scancode::ARROW_DOWN)] = "ARROW_DOWN"; + names[static_cast(Scancode::ARROW_RIGHT)] = "ARROW_RIGHT"; + names[static_cast(Scancode::ARROW_UP)] = "ARROW_UP"; + names[static_cast(Scancode::PAGE_DOWN)] = "PAGE_DOWN"; + names[static_cast(Scancode::PAGE_UP)] = "PAGE_UP"; + names[static_cast(Scancode::PRINT_SCREEN)] = "PRINT_SCREEN"; + names[static_cast(Scancode::PAUSE)] = "PAUSE"; + return names; +}(); +// + inline constexpr std::uint16_t PORT_PS2_DATA = 0x60; inline constexpr std::uint16_t PORT_PS2_STATUS = 0x64; inline constexpr std::uint8_t FLAG_PS2_OUTPUT_FULL = (1 << 0); @@ -38,6 +322,8 @@ std::uint8_t gKeyboardBuffer[KEY_BUFFER_LENGTH]; unsigned gBufferedKeys = 0; unsigned gKeyPos = 0; +constinit std::array gKeyStates; + __attribute__((no_caller_saved_registers)) void pushKey(std::uint8_t data) noexcept { @@ -48,10 +334,24 @@ void pushKey(std::uint8_t data) noexcept ++gBufferedKeys; gKeyPos = (gKeyPos + 1) % KEY_BUFFER_LENGTH; } + +void setKeyDown(Scancode scancode, bool down) noexcept +{ + const std::uint16_t index = static_cast(scancode); + const std::uint16_t byte = index / 8; + const std::uint16_t bit = index % 8; + + if (down) + { + gKeyStates[byte] |= (1 << bit); + } + else + { + gKeyStates[byte] &= ~(1 << bit); + } +} } -namespace baos::ps2 -{ inline bool waitForResponse(unsigned tries = -1) noexcept { for (unsigned t = 0; t < tries; ++t) @@ -219,11 +519,20 @@ void isrKeyboard(InterruptFrame* interruptFrame) noexcept return result; } +bool isKeyDown(Scancode scancode) noexcept +{ + const std::uint16_t index = static_cast(scancode); + const std::uint16_t byte = index / 8; + const std::uint16_t bit = index % 8; + + return (gKeyStates[byte] & (1 << bit)) != 0; +} + bool gNextIsRelease = false; -bool gNextIsExtended = false; -bool gNextIsMoreExtended = false; -bool gNextIsExtendedest = false; -bool gPrevWasExtendedest = false; +bool gNextIsExtended = false; // we've scanned a 0xE0 and are waiting for the second half +bool gNextIsMoreExtended = false; // we've scanned a 0xE0 and a 0x12, and are waiting for the rest of the print screen key (TODO: print screen up is probably broken!) +bool gNextIsExtendedest = false; // this is getting hilarious... this basically means we're somewhere inside the 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77 sequence for the pause key +bool gPrevWasExtendedest = false; // we just sent the pause key press, send a release after (because it doesn't get generated) bool readKey(KeyEvent& outEvent) noexcept { @@ -292,273 +601,61 @@ bool readKey(KeyEvent& outEvent) noexcept } else { - scancode |= 0xE000; + scancode |= 0x0100; } } outEvent.scancode = static_cast(scancode); outEvent.down = !gNextIsRelease; - outEvent.repeat = false; // TODO + outEvent.repeat = outEvent.down && isKeyDown(outEvent.scancode); + + setKeyDown(outEvent.scancode, outEvent.down); // reset state gNextIsExtendedest = gNextIsMoreExtended = gNextIsRelease = gNextIsExtended = false; return true; } +bool readChar(char& outChar) noexcept +{ + KeyEvent event; + while (readKey(event)) + { + if (!event.down) { + continue; + } + if (keyToChar(event.scancode, outChar)) { + return true; + } + } + return false; +} + const char* keyName(Scancode scancode) noexcept { - switch (scancode) + return SCANCODE_NAMES[static_cast(scancode)]; +} + +bool keyToChar(Scancode scancode, char& outChar) noexcept +{ + const Keymap& keymap = KEYMAP_DE_DE; + char result = '\0'; + if (isKeyDown(Scancode::RIGHT_ALT)) { - case Scancode::INVALID: - default: - return "INVALID"; - case Scancode::F9: - return "F9"; - case Scancode::F5: - return "F5"; - case Scancode::F3: - return "F3"; - case Scancode::F1: - return "F1"; - case Scancode::F2: - return "F2"; - case Scancode::F12: - return "F12"; - case Scancode::F10: - return "F10"; - case Scancode::F8: - return "F8"; - case Scancode::F6: - return "F6"; - case Scancode::F4: - return "F4"; - case Scancode::TAB: - return "TAB"; - case Scancode::BACKTICK: - return "BACKTICK"; - case Scancode::LEFT_ALT: - return "LEFT_ALT"; - case Scancode::LEFT_SHIFT: - return "LEFT_SHIFT"; - case Scancode::LEFT_CONTROL: - return "LEFT_CONTROL"; - case Scancode::Q: - return "Q"; - case Scancode::_1: - return "_1"; - case Scancode::Z: - return "Z"; - case Scancode::S: - return "S"; - case Scancode::A: - return "A"; - case Scancode::W: - return "W"; - case Scancode::_2: - return "_2"; - case Scancode::C: - return "C"; - case Scancode::X: - return "X"; - case Scancode::D: - return "D"; - case Scancode::E: - return "E"; - case Scancode::_4: - return "_4"; - case Scancode::_3: - return "_3"; - case Scancode::SPACE: - return "SPACE"; - case Scancode::V: - return "V"; - case Scancode::F: - return "F"; - case Scancode::T: - return "T"; - case Scancode::R: - return "R"; - case Scancode::_5: - return "_5"; - case Scancode::N: - return "N"; - case Scancode::B: - return "B"; - case Scancode::H: - return "H"; - case Scancode::G: - return "G"; - case Scancode::Y: - return "Y"; - case Scancode::_6: - return "_6"; - case Scancode::M: - return "M"; - case Scancode::J: - return "J"; - case Scancode::U: - return "U"; - case Scancode::_7: - return "_7"; - case Scancode::_8: - return "_8"; - case Scancode::COMMA: - return "COMMA"; - case Scancode::K: - return "K"; - case Scancode::I: - return "I"; - case Scancode::O: - return "O"; - case Scancode::_0: - return "_0"; - case Scancode::_9: - return "_9"; - case Scancode::DOT: - return "DOT"; - case Scancode::SLASH: - return "SLASH"; - case Scancode::L: - return "L"; - case Scancode::SEMICOLON: - return "SEMICOLON"; - case Scancode::P: - return "P"; - case Scancode::MINUS: - return "MINUS"; - case Scancode::APOSTROPHE: - return "APOSTROPHE"; - case Scancode::BRACKET_OPEN: - return "BRACKET_OPEN"; - case Scancode::EQUALS: - return "EQUALS"; - case Scancode::CAPSLOCK: - return "CAPSLOCK"; - case Scancode::RIGHT_SHIFT: - return "RIGHT_SHIFT"; - case Scancode::ENTER: - return "ENTER"; - case Scancode::BRACKET_CLOSE: - return "BRACKET_CLOSE"; - case Scancode::BACKSLASH: - return "BACKSLASH"; - case Scancode::BACKSPACE: - return "BACKSPACE"; - case Scancode::KP_1: - return "KP_1"; - case Scancode::KP_4: - return "KP_4"; - case Scancode::KP_7: - return "KP_7"; - case Scancode::KP_0: - return "KP_0"; - case Scancode::KP_DOT: - return "KP_DOT"; - case Scancode::KP_2: - return "KP_2"; - case Scancode::KP_5: - return "KP_5"; - case Scancode::KP_6: - return "KP_6"; - case Scancode::KP_8: - return "KP_8"; - case Scancode::ESCAPE: - return "ESCAPE"; - case Scancode::NUMLOCK: - return "NUMLOCK"; - case Scancode::F11: - return "F11"; - case Scancode::KP_PLUS: - return "KP_PLUS"; - case Scancode::KP_3: - return "KP_3"; - case Scancode::KP_MINUS: - return "KP_MINUS"; - case Scancode::KP_ASTERISK: - return "KP_ASTERISK"; - case Scancode::KP_9: - return "KP_9"; - case Scancode::SCROLLOCK: - return "SCROLLOCK"; - case Scancode::F7: - return "F7"; - case Scancode::MM_WWW_SEARCH: - return "MM_WWW_SEARCH"; - case Scancode::RIGHT_ALT: - return "RIGHT_ALT"; - case Scancode::RIGHT_CONTROL: - return "RIGHT_CONTROL"; - case Scancode::MM_PREV_TRACK: - return "MM_PREV_TRACK"; - case Scancode::LEFT_GUI: - return "LEFT_GUI"; - case Scancode::MM_WWW_FAVORITES: - return "MM_WWW_FAVORITES"; - case Scancode::MM_VOLUME_DOWN: - return "MM_VOLUME_DOWN"; - case Scancode::MM_MUTE: - return "MM_MUTE"; - case Scancode::RIGHT_GUI: - return "RIGHT_GUI"; - case Scancode::MM_WWW_STOP: - return "MM_WWW_STOP"; - case Scancode::MM_CALCULATOR: - return "MM_CALCULATOR"; - case Scancode::APPS: - return "APPS"; - case Scancode::MM_WWW_FORWARD: - return "MM_WWW_FORWARD"; - case Scancode::MM_VOLUME_UP: - return "MM_VOLUME_UP"; - case Scancode::MM_PLAY_PAUSE: - return "MM_PLAY_PAUSE"; - case Scancode::ACPI_POWER: - return "ACPI_POWER"; - case Scancode::MM_WWW_BACK: - return "MM_WWW_BACK"; - case Scancode::MM_WWW_HOME: - return "MM_WWW_HOME"; - case Scancode::MM_STOP: - return "MM_STOP"; - case Scancode::ACPI_SLEEP: - return "ACPI_SLEEP"; - case Scancode::MM_MY_COMPUTER: - return "MM_MY_COMPUTER"; - case Scancode::MM_EMAIL: - return "MM_EMAIL"; - case Scancode::KP_SLASH: - return "KP_SLASH"; - case Scancode::MM_NEXT_TRACK: - return "MM_NEXT_TRACK"; - case Scancode::MM_MEDIA_SELECT: - return "MM_MEDIA_SELECT"; - case Scancode::KP_ENTER: - return "KP_ENTER"; - case Scancode::ACPI_WAKE: - return "ACPI_WAKE"; - case Scancode::END: - return "END"; - case Scancode::ARROW_LEFT: - return "ARROW_LEFT"; - case Scancode::HOME: - return "HOME"; - case Scancode::INSERT: - return "INSERT"; - case Scancode::DELETE: - return "DELETE"; - case Scancode::ARROW_DOWN: - return "ARROW_DOWN"; - case Scancode::ARROW_RIGHT: - return "ARROW_RIGHT"; - case Scancode::ARROW_UP: - return "ARROW_UP"; - case Scancode::PAGE_DOWN: - return "PAGE_DOWN"; - case Scancode::PAGE_UP: - return "PAGE_UP"; - case Scancode::PRINT_SCREEN: - return "PRINT_SCREEN"; - case Scancode::PAUSE: - return "PAUSE"; + result = keymap.altGredKeys[static_cast(scancode)]; } + else if (isKeyDown(Scancode::LEFT_SHIFT) || isKeyDown(Scancode::RIGHT_SHIFT)) + { + result = keymap.shiftedKeys[static_cast(scancode)]; + } + else + { + result = keymap.regularKeys[static_cast(scancode)]; + } + if (result != '\0') + { + outChar = result; + return true; + } + return false; } } diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index f8887f6..475e517 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -243,7 +243,8 @@ void kernel_main() std::puts("This is BadAppleOS and everything is fine!\n"); - __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main); + // __enterUsermode(SEGIDX_USER_CODE, SEGIDX_USER_DATA, &tss.rsp0, &main); + main(); // for now run it in kernel mode, user mode doesn't work yet while (true) { ps2::KeyEvent event;