Started implementing a C++ stdlib. And improved the print function by adding newline support and scrolling.

This commit is contained in:
Patrick 2024-01-10 22:46:44 +01:00
parent 0b05970c71
commit 1756b6a1a9
8 changed files with 116 additions and 27 deletions

View File

@ -26,6 +26,8 @@ os_sources = Split('''
src/kernel/startup.cpp src/kernel/startup.cpp
src/os/tty.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]}') env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0]} {crtbegin_o} $_LIBFLAGS {crtend_o} {crtn_o[0]}')

14
include/cstring Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#if !defined(BAD_APPLE_OS_CSTRING_HPP_INCLUDED)
#define BAD_APPLE_OS_CSTRING_HPP_INCLUDED
#include <string.h>
namespace std
{
using ::strlen;
}
#endif // !defined(BAD_APPLE_OS_CSTRING_HPP_INCLUDED)

View File

@ -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)

View File

@ -35,17 +35,12 @@ struct VgaDoubleColor
VgaColor background : 4 = VgaColor::BLACK; VgaColor background : 4 = VgaColor::BLACK;
}; };
[[nodiscard]] size_t strlen(const char* str); // TODO: move to standard lib
void initialize(); void initialize();
void setColor(VgaDoubleColor color); void setColor(VgaDoubleColor color);
void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY); void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY);
void putChar(char chr); void putChar(char chr);
void write(const char* data, size_t size); void write(const char* data, size_t size);
void write(const char* data);
inline void write(const char* data)
{
write(data, strlen(data));
}
} // namespace tty } // namespace tty
#endif // OS_TTY_HPP_INCLUDED #endif // OS_TTY_HPP_INCLUDED

19
include/string.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#if !defined(BAD_APPLE_OS_STRING_H_INCLUDED)
#define BAD_APPLE_OS_STRING_H_INCLUDED
#include <stddef.h>
#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)

View File

@ -1,5 +1,3 @@
#include <stddef.h>
#include <stdint.h>
#include "os/tty.hpp" #include "os/tty.hpp"
@ -17,7 +15,15 @@ extern "C" void kernel_main(void)
{ {
/* Initialize terminal interface */ /* Initialize terminal interface */
tty::initialize(); tty::initialize();
/* Newline support is left as an exercise. */
tty::write("Hello, kernel World!\n"); tty::write("Hello, kernel World!\n");
while (true)
{
for (char chr = 'A'; chr <= 'Z'; ++chr)
{
char buf[2] = {chr, '\n'};
tty::write(buf, 2);
}
}
} }

View File

@ -1,6 +1,8 @@
#include "os/tty.hpp" #include "os/tty.hpp"
#include <cstring>
namespace tty namespace tty
{ {
namespace namespace
@ -8,6 +10,11 @@ namespace
inline const size_t VGA_WIDTH = 80; inline const size_t VGA_WIDTH = 80;
inline const size_t VGA_HEIGHT = 25; inline const size_t VGA_HEIGHT = 25;
size_t gTerminalRow = 0;
size_t gTerminalColumn = 0;
VgaDoubleColor gTerminalColor = VgaDoubleColor();
uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
constexpr uint8_t vgaEntryColor(VgaDoubleColor color) constexpr uint8_t vgaEntryColor(VgaDoubleColor color)
{ {
return static_cast<uint8_t>(color.foreground) | static_cast<uint8_t>(color.background) << 4; return static_cast<uint8_t>(color.foreground) | static_cast<uint8_t>(color.background) << 4;
@ -18,19 +25,28 @@ constexpr uint16_t vgaEntry(const unsigned char chr, const VgaDoubleColor color)
return static_cast<uint16_t>(chr) | static_cast<uint16_t>(vgaEntryColor(color) << 8); return static_cast<uint16_t>(chr) | static_cast<uint16_t>(vgaEntryColor(color) << 8);
} }
size_t gTerminalRow = 0; void newline()
size_t gTerminalColumn = 0;
VgaDoubleColor gTerminalColor = VgaDoubleColor();
uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
}
size_t strlen(const char* str) // TODO: move to standard lib
{ {
size_t len = 0; gTerminalColumn = 0;
while (str[len] != '\0') { if (gTerminalRow < VGA_HEIGHT - 1)
++len; {
++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() void initialize()
@ -61,11 +77,7 @@ void putChar(char chr)
putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow); putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow);
if (++gTerminalColumn == VGA_WIDTH) if (++gTerminalColumn == VGA_WIDTH)
{ {
gTerminalColumn = 0; newline();
if (++gTerminalRow == VGA_HEIGHT)
{
gTerminalRow = 0;
}
} }
} }
@ -73,7 +85,19 @@ void write(const char* data, size_t size)
{ {
for (size_t idx = 0; idx < size; idx++) 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));
}
} }

14
src/stdlib/string.cpp Normal file
View File

@ -0,0 +1,14 @@
#include <string.h>
extern "C"
{
size_t strlen(const char* str) noexcept
{
size_t len = 0;
while (str[len] != '\0') {
++len;
}
return len;
}
}