diff --git a/SConstruct b/SConstruct index 1145ad3..c649290 100644 --- a/SConstruct +++ b/SConstruct @@ -26,6 +26,8 @@ os_sources = Split(''' src/kernel/startup.cpp src/os/tty.cpp + + src/stdlib/string.cpp ''') env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0]} {crtbegin_o} $_LIBFLAGS {crtend_o} {crtn_o[0]}') diff --git a/include/cstring b/include/cstring new file mode 100644 index 0000000..42753a9 --- /dev/null +++ b/include/cstring @@ -0,0 +1,14 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CSTRING_HPP_INCLUDED) +#define BAD_APPLE_OS_CSTRING_HPP_INCLUDED + +#include + +namespace std +{ +using ::strlen; +} + +#endif // !defined(BAD_APPLE_OS_CSTRING_HPP_INCLUDED) diff --git a/include/detail/attributes.h b/include/detail/attributes.h new file mode 100644 index 0000000..0f04105 --- /dev/null +++ b/include/detail/attributes.h @@ -0,0 +1,15 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_DETAIL_ATTRIBUTES_H_INCLUDED) +#define BAD_APPLE_OS_DETAIL_ATTRIBUTES_H_INCLUDED + +#if defined(__cplusplus) +#define BA_CXX_NODISCARD [[nodiscard]] +#define BA_CXX_NOEXCEPT noexcept +#else +#define BA_CXX_NODISCARD +#define BA_CXX_NOEXCEPT +#endif + +#endif // !defined(BAD_APPLE_OS_DETAIL_ATTRIBUTES_H_INCLUDED) diff --git a/include/os/tty.hpp b/include/os/tty.hpp index 9ea9367..ea5f62f 100644 --- a/include/os/tty.hpp +++ b/include/os/tty.hpp @@ -35,17 +35,12 @@ struct VgaDoubleColor VgaColor background : 4 = VgaColor::BLACK; }; -[[nodiscard]] size_t strlen(const char* str); // TODO: move to standard lib void initialize(); void setColor(VgaDoubleColor color); void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY); void putChar(char chr); void write(const char* data, size_t size); - -inline void write(const char* data) -{ - write(data, strlen(data)); -} +void write(const char* data); } // namespace tty #endif // OS_TTY_HPP_INCLUDED diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..e23b53a --- /dev/null +++ b/include/string.h @@ -0,0 +1,19 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_STRING_H_INCLUDED) +#define BAD_APPLE_OS_STRING_H_INCLUDED + +#include + +#include "./detail/attributes.h" + +#if defined(__cplusplus) +extern "C" { +#endif +BA_CXX_NODISCARD size_t strlen(const char* str) BA_CXX_NOEXCEPT; +#if defined(__cplusplus) +} +#endif + +#endif // !defined(BAD_APPLE_OS_STRING_H_INCLUDED) diff --git a/src/kernel/startup.cpp b/src/kernel/startup.cpp index 038563e..25b3697 100644 --- a/src/kernel/startup.cpp +++ b/src/kernel/startup.cpp @@ -1,5 +1,3 @@ -#include -#include #include "os/tty.hpp" @@ -17,7 +15,15 @@ extern "C" void kernel_main(void) { /* Initialize terminal interface */ tty::initialize(); - - /* Newline support is left as an exercise. */ + tty::write("Hello, kernel World!\n"); + + while (true) + { + for (char chr = 'A'; chr <= 'Z'; ++chr) + { + char buf[2] = {chr, '\n'}; + tty::write(buf, 2); + } + } } diff --git a/src/os/tty.cpp b/src/os/tty.cpp index 1bbec74..4ec42a6 100644 --- a/src/os/tty.cpp +++ b/src/os/tty.cpp @@ -1,6 +1,8 @@ #include "os/tty.hpp" +#include + namespace tty { namespace @@ -8,6 +10,11 @@ namespace inline const size_t VGA_WIDTH = 80; inline const size_t VGA_HEIGHT = 25; +size_t gTerminalRow = 0; +size_t gTerminalColumn = 0; +VgaDoubleColor gTerminalColor = VgaDoubleColor(); +uint16_t* gTerminalBuffer = reinterpret_cast(0xB8000); + constexpr uint8_t vgaEntryColor(VgaDoubleColor color) { return static_cast(color.foreground) | static_cast(color.background) << 4; @@ -18,19 +25,28 @@ constexpr uint16_t vgaEntry(const unsigned char chr, const VgaDoubleColor color) return static_cast(chr) | static_cast(vgaEntryColor(color) << 8); } -size_t gTerminalRow = 0; -size_t gTerminalColumn = 0; -VgaDoubleColor gTerminalColor = VgaDoubleColor(); -uint16_t* gTerminalBuffer = reinterpret_cast(0xB8000); -} - -size_t strlen(const char* str) // TODO: move to standard lib +void newline() { - size_t len = 0; - while (str[len] != '\0') { - ++len; + gTerminalColumn = 0; + if (gTerminalRow < VGA_HEIGHT - 1) + { + ++gTerminalRow; } - return len; + else + { + // scrolling up + for (size_t y = 0; y < VGA_HEIGHT - 1; ++y) + { + // TODO: this is where I'd put my memcpy. If I had one. + for (size_t x = 0; x < VGA_WIDTH; ++x) + { + const size_t indexTo = y * VGA_WIDTH + x; + const size_t indexFrom = (y + 1) * VGA_WIDTH + x; + gTerminalBuffer[indexTo] = gTerminalBuffer[indexFrom]; + } + } + } +} } void initialize() @@ -61,11 +77,7 @@ void putChar(char chr) putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow); if (++gTerminalColumn == VGA_WIDTH) { - gTerminalColumn = 0; - if (++gTerminalRow == VGA_HEIGHT) - { - gTerminalRow = 0; - } + newline(); } } @@ -73,7 +85,19 @@ void write(const char* data, size_t size) { for (size_t idx = 0; idx < size; idx++) { - putChar(data[idx]); + if (data[idx] == '\n') + { + newline(); + } + else + { + putChar(data[idx]); + } } } + +void write(const char* data) +{ + write(data, std::strlen(data)); +} } diff --git a/src/stdlib/string.cpp b/src/stdlib/string.cpp new file mode 100644 index 0000000..d29de0b --- /dev/null +++ b/src/stdlib/string.cpp @@ -0,0 +1,14 @@ + +#include + +extern "C" +{ +size_t strlen(const char* str) noexcept +{ + size_t len = 0; + while (str[len] != '\0') { + ++len; + } + return len; +} +}