Refactor screen ouput from main console code

This commit is contained in:
Justin C. Miller
2018-04-24 09:32:57 -07:00
parent eb13f1f4fb
commit 94de87ef86
5 changed files with 224 additions and 196 deletions

View File

@@ -51,7 +51,6 @@ WARNFLAGS += -Wno-attributes -Wno-sign-compare -Wno-multichar
WARNFLAGS += -Wno-div-by-zero -Wno-endif-labels -Wno-pragmas WARNFLAGS += -Wno-div-by-zero -Wno-endif-labels -Wno-pragmas
WARNFLAGS += -Wno-format-extra-args -Wno-unused-result WARNFLAGS += -Wno-format-extra-args -Wno-unused-result
WARNFLAGS += -Wno-deprecated-declarations -Wno-unused-function WARNFLAGS += -Wno-deprecated-declarations -Wno-unused-function
WARNFLAGS += -Wno-unused-but-set-parameter
ASFLAGS ?= ASFLAGS ?=
ASFLAGS += -p $(BUILD_D)/versions.s ASFLAGS += -p $(BUILD_D)/versions.s
@@ -62,7 +61,7 @@ CFLAGS += -std=c11 -mcmodel=large
CXXFLAGS := $(INCLUDES) $(DEPENDFLAGS) $(BASEFLAGS) $(WARNFLAGS) CXXFLAGS := $(INCLUDES) $(DEPENDFLAGS) $(BASEFLAGS) $(WARNFLAGS)
CXXFLAGS += -DGIT_VERSION="\"$(VERSION)\"" CXXFLAGS += -DGIT_VERSION="\"$(VERSION)\""
CXXFLAGS += -std=c++14 -mcmodel=large CXXFLAGS += -std=c++14 -mcmodel=large -fno-rtti
BOOT_CFLAGS := $(INCLUDES) $(DEPENDFLAGS) $(BASEFLAGS) $(WARNFLAGS) BOOT_CFLAGS := $(INCLUDES) $(DEPENDFLAGS) $(BASEFLAGS) $(WARNFLAGS)
BOOT_CFLAGS += -std=c11 -I src/boot -fPIC -fshort-wchar BOOT_CFLAGS += -std=c11 -I src/boot -fPIC -fshort-wchar

View File

@@ -2,85 +2,216 @@
#include "io.h" #include "io.h"
const char digits[] = "0123456789abcdef"; const char digits[] = "0123456789abcdef";
console g_console;
console *console::default_console = nullptr;
console::console(const font &f, const screen &s, void *scratch, size_t len) : class console_out_screen
m_font(f),
m_screen(s),
m_size(s.width() / f.width(), s.height() / f.height()),
m_fg(0xffffff),
m_bg(0),
m_first(0),
m_length(len),
m_data(nullptr),
m_attrs(nullptr),
m_palette(nullptr)
{ {
const unsigned count = m_size.size(); public:
const size_t palette_size = sizeof(screen::pixel_t) * 256; console_out_screen(const font &f, const screen &s, void *scratch, size_t len) :
const size_t attrs_size = 2 * count; m_font(f),
m_screen(s),
m_size(s.width() / f.width(), s.height() / f.height()),
m_fg(0xffffff),
m_bg(0),
m_first(0),
m_length(len),
m_data(nullptr),
m_attrs(nullptr),
m_palette(nullptr)
{
const unsigned count = m_size.size();
const size_t palette_size = sizeof(screen::pixel_t) * 256;
const size_t attrs_size = 2 * count;
if (len >= count) { if (len >= count) {
// We have enough scratch space to keep the contents of the screen // We have enough scratch space to keep the contents of the screen
m_data = static_cast<char *>(scratch); m_data = static_cast<char *>(scratch);
for (unsigned i = 0; i < count; ++i) for (unsigned i = 0; i < count; ++i)
m_data[i] = 0; m_data[i] = 0;
}
if (len >= count + palette_size + attrs_size) {
// We have enough scratch space to also keep the colors of the text
m_palette = reinterpret_cast<screen::pixel_t *>(m_data + count);
unsigned index = 0;
// Manually add the 16 basic ANSI colors
m_palette[index++] = m_screen.color(0x00, 0x00, 0x00);
m_palette[index++] = m_screen.color(0xcd, 0x00, 0x00);
m_palette[index++] = m_screen.color(0x00, 0xcd, 0x00);
m_palette[index++] = m_screen.color(0xcd, 0xcd, 0x00);
m_palette[index++] = m_screen.color(0x00, 0x00, 0xee);
m_palette[index++] = m_screen.color(0xcd, 0x00, 0xcd);
m_palette[index++] = m_screen.color(0x00, 0xcd, 0xcd);
m_palette[index++] = m_screen.color(0xe5, 0xe5, 0xe5);
m_palette[index++] = m_screen.color(0x7f, 0x7f, 0x7f);
m_palette[index++] = m_screen.color(0xff, 0x00, 0x00);
m_palette[index++] = m_screen.color(0x00, 0xff, 0x00);
m_palette[index++] = m_screen.color(0xff, 0xff, 0x00);
m_palette[index++] = m_screen.color(0x00, 0x50, 0xff);
m_palette[index++] = m_screen.color(0xff, 0x00, 0xff);
m_palette[index++] = m_screen.color(0x00, 0xff, 0xff);
m_palette[index++] = m_screen.color(0xff, 0xff, 0xff);
// Build the high-color portion of the table
const uint32_t intensity[] = {0, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
const uint32_t intensities = sizeof(intensity) / sizeof(uint32_t);
for (uint32_t r = 0; r < intensities; ++r) {
for (uint32_t g = 0; g < intensities; ++g) {
for (uint32_t b = 0; b < intensities; ++b) {
m_palette[index++] = m_screen.color(
intensity[r], intensity[g], intensity[b]);
}
}
}
// Build the greyscale portion of the table
for (uint8_t i = 0x08; i <= 0xee; i += 10)
m_palette[index++] = m_screen.color(i, i, i);
set_color(7, 0); // Grey on black default
m_attrs = reinterpret_cast<uint16_t *>(m_data + count + palette_size);
for (unsigned i = 0; i < count; ++i)
m_attrs[i] = m_attr;
}
repaint();
} }
if (len >= count + palette_size + attrs_size) { void repaint()
// We have enough scratch space to also keep the colors of the text {
m_palette = reinterpret_cast<screen::pixel_t *>(m_data + count); m_screen.fill(m_bg);
if (!m_data) return;
unsigned index = 0; for (unsigned y = 0; y < m_size.y; ++y) {
const char *line = line_pointer(y);
const uint16_t *attrs = attr_pointer(y);
for (unsigned x = 0; x < m_size.x; ++x) {
const uint16_t attr = attrs[x];
// Manually add the 16 basic ANSI colors set_color(static_cast<uint8_t>(attr),
m_palette[index++] = m_screen.color(0x00, 0x00, 0x00); static_cast<uint8_t>(attr >> 8));
m_palette[index++] = m_screen.color(0xcd, 0x00, 0x00);
m_palette[index++] = m_screen.color(0x00, 0xcd, 0x00);
m_palette[index++] = m_screen.color(0xcd, 0xcd, 0x00);
m_palette[index++] = m_screen.color(0x00, 0x00, 0xee);
m_palette[index++] = m_screen.color(0xcd, 0x00, 0xcd);
m_palette[index++] = m_screen.color(0x00, 0xcd, 0xcd);
m_palette[index++] = m_screen.color(0xe5, 0xe5, 0xe5);
m_palette[index++] = m_screen.color(0x7f, 0x7f, 0x7f);
m_palette[index++] = m_screen.color(0xff, 0x00, 0x00);
m_palette[index++] = m_screen.color(0x00, 0xff, 0x00);
m_palette[index++] = m_screen.color(0xff, 0xff, 0x00);
m_palette[index++] = m_screen.color(0x00, 0x50, 0xff);
m_palette[index++] = m_screen.color(0xff, 0x00, 0xff);
m_palette[index++] = m_screen.color(0x00, 0xff, 0xff);
m_palette[index++] = m_screen.color(0xff, 0xff, 0xff);
// Build the high-color portion of the table m_font.draw_glyph(
const uint32_t intensity[] = {0, 0x5f, 0x87, 0xaf, 0xd7, 0xff}; m_screen,
const uint32_t intensities = sizeof(intensity) / sizeof(uint32_t); line[x] ? line[x] : ' ',
m_fg,
m_bg,
x * m_font.width(),
y * m_font.height());
}
}
}
for (uint32_t r = 0; r < intensities; ++r) { void scroll(unsigned lines)
for (uint32_t g = 0; g < intensities; ++g) { {
for (uint32_t b = 0; b < intensities; ++b) { if (!m_data) {
m_palette[index++] = m_screen.color( m_pos.x = 0;
intensity[r], intensity[g], intensity[b]); m_pos.y = 0;
} } else {
unsigned bytes = lines * m_size.x;
char *line = line_pointer(0);
for (unsigned i = 0; i < bytes; ++i)
*line++ = 0;
m_first = (m_first + lines) % m_size.y;
m_pos.y -= lines;
}
repaint();
}
void set_color(uint8_t fg, uint8_t bg)
{
if (!m_palette) return;
m_bg = m_palette[bg];
m_fg = m_palette[fg];
m_attr = (bg << 8) | fg;
}
void putc(char c)
{
char *line = line_pointer(m_pos.y);
uint16_t *attrs = attr_pointer(m_pos.y);
switch (c) {
case '\t':
m_pos.x = (m_pos.x + 4) / 4 * 4;
break;
case '\r':
m_pos.x = 0;
break;
case '\n':
m_pos.x = 0;
m_pos.y++;
break;
default: {
if (line) line[m_pos.x] = c;
if (attrs) attrs[m_pos.x] = m_attr;
const unsigned x = m_pos.x * m_font.width();
const unsigned y = m_pos.y * m_font.height();
m_font.draw_glyph(m_screen, c, m_fg, m_bg, x, y);
m_pos.x++;
} }
} }
// Build the greyscale portion of the table if (m_pos.x >= m_size.x) {
for (uint8_t i = 0x08; i <= 0xee; i += 10) m_pos.x = m_pos.x % m_size.x;
m_palette[index++] = m_screen.color(i, i, i); m_pos.y++;
}
set_color(7, 0); // Grey on black default if (m_pos.y >= m_size.y) {
m_attrs = reinterpret_cast<uint16_t *>(m_data + count + palette_size); scroll(1);
for (unsigned i = 0; i < count; ++i) line = line_pointer(m_pos.y);
m_attrs[i] = m_attr; }
} }
repaint(); private:
char * line_pointer(unsigned line)
{
if (!m_data) return nullptr;
return m_data + ((m_first + line) % m_size.y) * m_size.x;
}
if (default_console == nullptr) uint16_t * attr_pointer(unsigned line)
default_console = this; {
if (!m_attrs) return nullptr;
return m_attrs + ((m_first + line) % m_size.y) * m_size.x;
}
font m_font;
screen m_screen;
kutil::coord<unsigned> m_size;
kutil::coord<unsigned> m_pos;
screen::pixel_t m_fg, m_bg;
uint16_t m_attr;
size_t m_first;
size_t m_length;
char *m_data;
uint16_t *m_attrs;
screen::pixel_t *m_palette;
};
console_out_screen *
console_get_screen_out(const font &f, const screen &s, void *scratch, size_t len)
{
return nullptr;
//return new console_out_screen(f, s, scratch, len);
} }
static bool static bool
serial_ready() serial_ready()
{ {
@@ -93,122 +224,26 @@ serial_write(char c) {
outb(COM1, c); outb(COM1, c);
} }
char *
console::line_pointer(unsigned line) console::console() :
m_screen(nullptr)
{ {
if (!m_data) return nullptr;
return m_data + ((m_first + line) % m_size.y) * m_size.x;
}
uint16_t *
console::attr_pointer(unsigned line)
{
if (!m_attrs) return nullptr;
return m_attrs + ((m_first + line) % m_size.y) * m_size.x;
}
void
console::repaint()
{
m_screen.fill(m_bg);
if (!m_data) return;
for (unsigned y = 0; y < m_size.y; ++y) {
const char *line = line_pointer(y);
const uint16_t *attrs = attr_pointer(y);
for (unsigned x = 0; x < m_size.x; ++x) {
const uint16_t attr = attrs[x];
set_color(static_cast<uint8_t>(attr),
static_cast<uint8_t>(attr >> 8));
m_font.draw_glyph(
m_screen,
line[x] ? line[x] : ' ',
m_fg,
m_bg,
x * m_font.width(),
y * m_font.height());
}
}
} }
void void
console::set_color(uint8_t fg, uint8_t bg) console::set_color(uint8_t fg, uint8_t bg)
{ {
if (!m_palette) return; if (m_screen)
m_screen->set_color(fg, bg);
m_bg = m_palette[bg];
m_fg = m_palette[fg];
m_attr = (bg << 8) | fg;
} }
void void
console::scroll(unsigned lines)
{
if (!m_data) {
m_pos.x = 0;
m_pos.y = 0;
} else {
unsigned bytes = lines * m_size.x;
char *line = line_pointer(0);
for (unsigned i = 0; i < bytes; ++i)
*line++ = 0;
m_first = (m_first + lines) % m_size.y;
m_pos.y -= lines;
}
repaint();
}
size_t
console::puts(const char *message) console::puts(const char *message)
{ {
char *line = line_pointer(m_pos.y);
uint16_t *attrs = attr_pointer(m_pos.y);
size_t count = 0;
while (message && *message) { while (message && *message) {
const unsigned x = m_pos.x * m_font.width(); char c = *message++;
const unsigned y = m_pos.y * m_font.height(); if (m_screen) m_screen->putc(c);
const char c = *message++;
++count;
switch (c) {
case '\t':
m_pos.x = (m_pos.x + 4) / 4 * 4;
break;
case '\r':
m_pos.x = 0;
break;
case '\n':
serial_write('\r');
m_pos.x = 0;
m_pos.y++;
break;
default:
if (line) line[m_pos.x] = c;
if (attrs) attrs[m_pos.x] = m_attr;
m_font.draw_glyph(m_screen, c, m_fg, m_bg, x, y);
m_pos.x++;
}
if (m_pos.x >= m_size.x) {
m_pos.x = m_pos.x % m_size.x;
m_pos.y++;
}
if (m_pos.y >= m_size.y) {
scroll(1);
line = line_pointer(m_pos.y);
}
serial_write(c); serial_write(c);
if (c == '\n') serial_write('\r');
} }
return count;
} }

View File

@@ -4,20 +4,17 @@
#include "font.h" #include "font.h"
#include "screen.h" #include "screen.h"
struct console_data; class console_out_screen;
class console class console
{ {
public: public:
console(const font &f, const screen &s, void *scratch, size_t len); console();
void repaint();
void scroll(unsigned lines);
void set_color(uint8_t fg, uint8_t bg); void set_color(uint8_t fg, uint8_t bg);
size_t puts(const char *message); void puts(const char *message);
size_t printf(const char *fmt, ...); void printf(const char *fmt, ...);
template <typename T> template <typename T>
void put_hex(T x); void put_hex(T x);
@@ -25,30 +22,20 @@ public:
template <typename T> template <typename T>
void put_dec(T x); void put_dec(T x);
static console * get() { return default_console; } static console * get();
private: private:
char * line_pointer(unsigned line); console_out_screen *m_screen;
uint16_t * attr_pointer(unsigned line);
font m_font;
screen m_screen;
kutil::coord<unsigned> m_size;
kutil::coord<unsigned> m_pos;
screen::pixel_t m_fg, m_bg;
uint16_t m_attr;
size_t m_first;
size_t m_length;
char *m_data;
uint16_t *m_attrs;
screen::pixel_t *m_palette;
static console *default_console;
}; };
extern console g_console;
inline console * console::get() { return &g_console; }
console_out_screen * console_get_screen_out(
const font &f, const screen &s, void *scratch, size_t len);
extern const char digits[]; extern const char digits[];
template <typename T> template <typename T>

View File

@@ -14,6 +14,9 @@ extern "C" {
void kernel_main(popcorn_data *header); void kernel_main(popcorn_data *header);
} }
inline void * operator new (size_t, void *p) throw() { return p; }
/*
console console
load_console(const popcorn_data *header) load_console(const popcorn_data *header)
{ {
@@ -36,11 +39,12 @@ load_console(const popcorn_data *header)
return cons; return cons;
} }
*/
void void
kernel_main(popcorn_data *header) kernel_main(popcorn_data *header)
{ {
console cons = load_console(header); console *cons = new (&g_console) console();
memory_initialize_managers( memory_initialize_managers(
header->memory_map, header->memory_map,
@@ -50,13 +54,13 @@ kernel_main(popcorn_data *header)
interrupts_init(); interrupts_init();
interrupts_enable(); interrupts_enable();
cons.puts("Interrupts initialized.\n"); g_console.puts("Interrupts initialized.\n");
device_manager devices(header->acpi_table); device_manager devices(header->acpi_table);
// int x = 1 / 0; // int x = 1 / 0;
// __asm__ __volatile__("int $15"); // __asm__ __volatile__("int $15");
cons.puts("boogity!"); g_console.puts("boogity!");
do_the_set_registers(header); do_the_set_registers(header);
} }

View File

@@ -0,0 +1,3 @@
extern "C" {
void __cxa_pure_virtual() { while(1); }
}