xaizek / tos (License: GPLv3 only) (since 2018-12-07)
This is an alternative version of sources presented as part of Write Your Own OS video tutorial by Viktor Engelmann.
<root> / src / hwcomm / Screen.hpp (3e8c230091477561deaf673cbac1fcf1bfcb8844) (2,003B) (mode 100644) [raw]
#ifndef TOS__HWCOMM__SCREEN_HPP__
#define TOS__HWCOMM__SCREEN_HPP__

#include <cstdint>

#include <new>

namespace hwcomm {

class Screen
{
public:
    static constexpr int lines = 25;
    static constexpr int cols = 80;

    Screen() {
        clear();
    }

public:
    void print(const char str[])
    {
        for (int i = 0; str[i] != '\0'; ++i) {
            switch (str[i]) {
                int pos;

                case '\n':
                    nextLine();
                    break;

                default:
                    pos = y*cols + x;
                    area[pos] = (area[pos] & attrMask) | str[i];
                    ++x;
                    break;
            }

            if (x == cols) {
                nextLine();
            }
        }
    }

    void invertAt(int x, int y)
    {
        if (x < 0 || x >= cols || y < 0 || y >= lines) {
            return;
        }

        const int pos = y*cols + x;
        area[pos] = (area[pos] & 0x0f00) << 4
                  | (area[pos] & 0xf000) >> 4
                  | (area[pos] & 0x00ff);
    }

    void clear()
    {
        for (int i = 0; i < areaSize; ++i) {
            area[i] = fillValue;
        }
        x = 0;
        y = 0;
    }

private:
    void nextLine()
    {
        ++y;
        x = 0;

        if (y != lines) {
            return;
        }

        y = lines - 1;

        // Scroll buffer by one line.
        for (int i = 0; i < areaSize - cols; ++i) {
            area[i] = area[i + cols];
        }
        for (int i = areaSize - cols; i < areaSize; ++i) {
            area[i] = fillValue;
        }
    }

private:
    std::uint16_t *area = new(areaStart) std::uint16_t[areaSize];
    int x = 0;
    int y = 0;

    static constexpr auto areaStart = reinterpret_cast<void *>(0xb8000);
    static constexpr int areaSize = lines*cols;
    static constexpr std::uint16_t attrMask = 0xff00;
    static constexpr std::uint16_t fillValue = 0x0f00;
};

}

#endif // TOS__HWCOMM__SCREEN_HPP__
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master