Add console, klog, and writef modules.
They are not complete, but adding to checkpoint progress.
This commit is contained in:
parent
e214a9c3de
commit
06242a0c9f
72
src/hulk/console.d
Normal file
72
src/hulk/console.d
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* HULK Console functionality.
|
||||||
|
*/
|
||||||
|
module hulk.console;
|
||||||
|
|
||||||
|
import hulk.framebuffer;
|
||||||
|
import hulk.kfont;
|
||||||
|
|
||||||
|
struct Console
|
||||||
|
{
|
||||||
|
Framebuffer * m_fb;
|
||||||
|
size_t m_width;
|
||||||
|
size_t m_height;
|
||||||
|
size_t m_x;
|
||||||
|
size_t m_y;
|
||||||
|
|
||||||
|
public void initialize(Framebuffer * fb)
|
||||||
|
{
|
||||||
|
m_fb = fb;
|
||||||
|
m_width = fb.width / kfont.advance;
|
||||||
|
m_height = fb.height / kfont.line_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
m_fb.clear();
|
||||||
|
m_x = 0u;
|
||||||
|
m_y = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(char ch)
|
||||||
|
{
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
m_x = 0u;
|
||||||
|
m_y++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_char(m_x, m_y, ch);
|
||||||
|
m_x++;
|
||||||
|
if (m_x == m_width)
|
||||||
|
{
|
||||||
|
m_x = 0u;
|
||||||
|
m_y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_y == m_height)
|
||||||
|
{
|
||||||
|
m_y--;
|
||||||
|
m_fb.copy_rows_up(fb_y(m_height - 1u),
|
||||||
|
(m_height - 1u) * kfont.line_height,
|
||||||
|
kfont.line_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void render_char(size_t x, size_t y, char ch)
|
||||||
|
{
|
||||||
|
const(CharInfo) * ci = &kfont.chars[ch];
|
||||||
|
m_fb.blit_alpha_bitmap(fb_x(x) + ci.left, fb_y(y) + ci.top - ci.height, ci.bitmap, ci.width, ci.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private size_t fb_x(size_t x)
|
||||||
|
{
|
||||||
|
return x * kfont.advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private size_t fb_y(size_t y)
|
||||||
|
{
|
||||||
|
return m_fb.height - ((y + 1u) * kfont.line_height);
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,22 @@ struct Framebuffer
|
|||||||
/** Number of pixels in the frame buffer (whether visible or not). */
|
/** Number of pixels in the frame buffer (whether visible or not). */
|
||||||
private uint m_buffer_size;
|
private uint m_buffer_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer width.
|
||||||
|
*/
|
||||||
|
public @property uint width()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer height.
|
||||||
|
*/
|
||||||
|
public @property uint height()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a frame buffer.
|
* Initialize a frame buffer.
|
||||||
*
|
*
|
||||||
@ -168,6 +184,52 @@ struct Framebuffer
|
|||||||
blend_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height, color);
|
blend_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
* The foreground will be white (based on the alpha value), and the
|
||||||
|
* background black.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
*/
|
||||||
|
void blit_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap,
|
||||||
|
size_t width, size_t height)
|
||||||
|
{
|
||||||
|
y += height - 1u;
|
||||||
|
size_t bitmap_index;
|
||||||
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
|
{
|
||||||
|
for (size_t ix = 0u; ix < width; ix++)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x + ix, y);
|
||||||
|
ubyte alpha = alpha_bitmap[bitmap_index];
|
||||||
|
m_buffer[buffer_index] = (alpha << 16u) | (alpha << 8u) | alpha;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
* The foreground will be white (based on the alpha value), and the
|
||||||
|
* background black.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
*/
|
||||||
|
void blit_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap,
|
||||||
|
size_t width, size_t height)
|
||||||
|
{
|
||||||
|
blit_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy framebuffer rows up in the framebuffer.
|
* Copy framebuffer rows up in the framebuffer.
|
||||||
*
|
*
|
||||||
|
@ -6,11 +6,14 @@ module hulk.hulk;
|
|||||||
import hulk.header;
|
import hulk.header;
|
||||||
import hulk.bootinfo;
|
import hulk.bootinfo;
|
||||||
import hulk.framebuffer;
|
import hulk.framebuffer;
|
||||||
|
import hulk.console;
|
||||||
import hos.memory;
|
import hos.memory;
|
||||||
import ldc.attributes;
|
import ldc.attributes;
|
||||||
import hulk.kfont;
|
import hulk.kfont;
|
||||||
|
static import hulk.klog;
|
||||||
|
|
||||||
private __gshared Framebuffer fb;
|
private __gshared Framebuffer fb;
|
||||||
|
private __gshared Console console;
|
||||||
|
|
||||||
extern extern(C) __gshared ubyte _hulk_total_size;
|
extern extern(C) __gshared ubyte _hulk_total_size;
|
||||||
|
|
||||||
@ -44,6 +47,15 @@ extern(C) void hulk_start(ulong rdi, ulong rsi, ulong rdx, BootInfo * bootinfo)
|
|||||||
x += kfont.advance;
|
x += kfont.advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.initialize(&fb);
|
||||||
|
console.clear();
|
||||||
|
hulk.klog.initialize(&console);
|
||||||
|
|
||||||
|
for (size_t i = 1u; i != 0u; i++)
|
||||||
|
{
|
||||||
|
hulk.klog.writef("Hello! i = %010u\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
76
src/hulk/klog.d
Normal file
76
src/hulk/klog.d
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* HULK Kernel Log buffer.
|
||||||
|
*/
|
||||||
|
module hulk.klog;
|
||||||
|
|
||||||
|
import core.stdc.stdarg;
|
||||||
|
import hulk.console;
|
||||||
|
static import hulk.writef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kernel buffer size log.
|
||||||
|
* 16 gives a kernel buffer size of 64KB.
|
||||||
|
*/
|
||||||
|
enum size_t KLOG_SIZE_LOG = 16u;
|
||||||
|
|
||||||
|
/** Kernel buffer size. */
|
||||||
|
enum size_t KLOG_SIZE = 1u << KLOG_SIZE_LOG;
|
||||||
|
|
||||||
|
/** Kernel log buffer. */
|
||||||
|
private __gshared align(4096) char[KLOG_SIZE] klog_buffer;
|
||||||
|
|
||||||
|
/** Write index in the kernel log buffer. */
|
||||||
|
private __gshared size_t klog_index;
|
||||||
|
|
||||||
|
/** Pointer to the console to use for kernel log output. */
|
||||||
|
private __gshared Console * console;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the klog module.
|
||||||
|
*
|
||||||
|
* @param console Pointer to the Console to use for kernel output.
|
||||||
|
*/
|
||||||
|
void initialize(Console * console)
|
||||||
|
{
|
||||||
|
.console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string to the kernel log.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
* @param args Variable arguments structure.
|
||||||
|
*/
|
||||||
|
void writef(string s, va_list args)
|
||||||
|
{
|
||||||
|
hulk.writef.writef(s, args, function void(ubyte ch) {
|
||||||
|
console.write(ch);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string to the kernel log.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
*/
|
||||||
|
extern (C) void writef(string s, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, s);
|
||||||
|
writef(s, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string and newline to the console.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
*/
|
||||||
|
extern (C) void writefln(string s, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, s);
|
||||||
|
writef(s, args);
|
||||||
|
writef("\n", args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
151
src/hulk/writef.d
Normal file
151
src/hulk/writef.d
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* HULK Formatted stream writing support.
|
||||||
|
*/
|
||||||
|
module hulk.writef;
|
||||||
|
|
||||||
|
import core.stdc.stdarg;
|
||||||
|
|
||||||
|
alias ch_out_fn = void function(ubyte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a string and write characters to the given output function.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
* @param args Variable arguments structure.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
size_t writef(string s, va_list args, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
size_t length_written;
|
||||||
|
bool escape = false;
|
||||||
|
char pad = ' ';
|
||||||
|
size_t width;
|
||||||
|
foreach (char c; s)
|
||||||
|
{
|
||||||
|
if (escape)
|
||||||
|
{
|
||||||
|
if (c == 'x')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_hex(v, false, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if (c == 'X')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_hex(v, true, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if (c == 'u')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_udec(v, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if ((c == '0') && (width == 0u))
|
||||||
|
{
|
||||||
|
pad = '0';
|
||||||
|
}
|
||||||
|
else if (('0' <= c) && (c <= '9'))
|
||||||
|
{
|
||||||
|
width = (width * 10u) + (c - '0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch_out(c);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '%')
|
||||||
|
{
|
||||||
|
escape = true;
|
||||||
|
pad = ' ';
|
||||||
|
width = 0u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch_out(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return length_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a value in hexadecimal to the given output function.
|
||||||
|
*
|
||||||
|
* @param v Value to format.
|
||||||
|
* @param upper Whether to use uppercase letters.
|
||||||
|
* @param pad Pad character to use.
|
||||||
|
* @param width Field width.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
private size_t write_hex(ulong v, bool upper, char pad, size_t width, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
string hex_chars_lower = "0123456789abcdef";
|
||||||
|
string hex_chars_upper = "0123456789ABCDEF";
|
||||||
|
char[16] buf;
|
||||||
|
size_t i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong n = v & 0xFu;
|
||||||
|
buf[i] = upper ? hex_chars_upper[n] : hex_chars_lower[n];
|
||||||
|
v >>= 4u;
|
||||||
|
i++;
|
||||||
|
} while (v != 0u);
|
||||||
|
size_t length_written = i;
|
||||||
|
while (width > i)
|
||||||
|
{
|
||||||
|
ch_out(pad);
|
||||||
|
width--;
|
||||||
|
length_written++;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
ch_out(buf[i]);
|
||||||
|
} while (i != 0u);
|
||||||
|
return length_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a value in decimal to the given output function.
|
||||||
|
*
|
||||||
|
* @param v Value to format.
|
||||||
|
* @param pad Pad character to use.
|
||||||
|
* @param width Field width.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
private size_t write_udec(ulong v, char pad, size_t width, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
char[20] buf;
|
||||||
|
size_t i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong d = v % 10u;
|
||||||
|
buf[i] = cast(char)(d + '0');
|
||||||
|
v /= 10u;
|
||||||
|
i++;
|
||||||
|
} while (v != 0u);
|
||||||
|
size_t length_written = i;
|
||||||
|
while (width > i)
|
||||||
|
{
|
||||||
|
ch_out(pad);
|
||||||
|
width--;
|
||||||
|
length_written++;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
ch_out(buf[i]);
|
||||||
|
} while (i != 0u);
|
||||||
|
return length_written;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user