BASICFreak wrote:
EDIT:
Also, auto pos = 0 * vbe->LinBytesPerScanLine + 0 * (vbe->bpp /
;
so pos = 0 * x + 0 * y = 0 + 0 * y = 0 * y = 0??? no matter what value you have its always 0.
As a test, I was just plotting one pixel. Anyways, I've made some modifications to my program. All writing operations now happen to free_mem_start instead of the video memory, and then I copy it all over using your memcpy. I've reduced the size to 1 megabyte and the starting address to 1 megabyte. No issues so far.
There is certainly an improvement in speed, but it's hard to tell because I don't see "visual feedback" before each copy.
Code: Select all
uint8_t *mem;
uint8_t *free_mem_start;
auto xy_to_offset(int x, int y)
{
return y * vbe->LinBytesPerScanLine + x * (vbe->bpp / 8);
}
void draw_pixel(int x, int y, uint32_t color)
{
auto pos = xy_to_offset(x, y);
free_mem_start[pos] = color & 0xFF;
free_mem_start[pos + 1] = (color >> 8) & 0xFF;
free_mem_start[pos + 2] = (color >> 16) & 0xFF;
}
void draw_rectangle(int x, int y, int width, int height, uint32_t color)
{
for (int i = x; i < x + width; ++i)
{
for (int j = y; j < y + height; ++j)
{
draw_pixel(i, j, color);
}
}
}
extern bitmap_font font;
void draw_char(wchar_t c, int x, int y, int color)
{
auto index = index_of(font.Index, font.Index + font.Chars, c);
auto height = font.Height;
auto width = font.Widths[index];
auto bitmap = font.Bitmap +
index
* (height * 2);
for(auto cy = 0u; cy < height; ++cy)
{
for(auto cx = 0u; cx <= width; ++cx)
{
auto mask = (1 << (width - cx));
if(bitmap[cy * 2] & mask)
{
draw_pixel(x + cx, y + cy, color);
}
}
}
}
void copy_pixel(int x, int y, int x2, int y2)
{
auto pos = xy_to_offset(x, y);
auto pos2 = xy_to_offset(x2, y2);
free_mem_start[pos2] = free_mem_start[pos];
free_mem_start[pos2 + 1] = free_mem_start[pos + 1];
free_mem_start[pos2 + 2] = free_mem_start[pos + 2];
}
void copy_glyph(int x, int y, int x2, int y2)
{
for(auto cy = 0u; cy < font.Height; ++cy)
{
for(auto cx = 0u; cx < font.Width; ++cx)
{
copy_pixel(x + cx, y + cy, x2 + cx, y2 + cy);
}
}
}
size_t row = 0;
size_t column = 0;
size_t max_rows = 0;
size_t max_columns = 0;
void scroll()
{
if (row >= max_rows)
{
auto start = 0;
auto end = max_rows - 1;
for (auto it = start; it < end; ++it)
{
for (auto i = 0u; i < max_columns; ++i)
copy_glyph(i * font.Width, (it + 1) * font.Height,
i * font.Width, it * font.Height);
}
draw_rectangle(0, (max_rows - 1) * font.Height,
max_columns * font.Width, font.Height,
0);
row = max_rows - 1;
}
}
void draw_string(const wchar_t* s, int color = 0xFFFFFF)
{
auto len = strlen(s);
for (auto i = 0u; i < len; ++i)
{
if (s[i] == '\n')
{
++row;
column = 0;
}
else
{
auto index = index_of(font.Index, font.Index + font.Chars, s[i]);
auto width = font.Widths[index];
draw_char(s[i], column * width, row * font.Height, color);
++column;
}
scroll();
}
}
void print_memory_map()
{
wchar_t buf[100];
snprintf (buf, sizeof(buf),
"upper_mem = 0x%x, lower_mem = 0x%x\n"
"mmap_addr = 0x%x, mmap_length = 0x%x\n",
mbi->mem_lower, mbi->mem_upper,
mbi->mmap_addr, mbi->mmap_length);
write_serial_string(buf);
wchar_t buf2[100];
if (CHECK_BIT(mbi->flags, 6))
{
auto mmap = (multiboot_memory_map_t *) mbi->mmap_addr;
auto end = mbi->mmap_addr + mbi->mmap_length;
while((uint32_t) mmap < end)
{
snprintf (buf2, sizeof(buf2),
"size = %x, base_addr = %x, length = %x, type = %s\n",
(uint16_t) mmap->size,
mmap->addr_low,
mmap->len_low,
(mmap->type == MULTIBOOT_MEMORY_AVAILABLE
? L"available"
: L"reserved"));
write_serial_string(buf2);
mmap = (multiboot_memory_map_t *)
((uint32_t) mmap + mmap->size + sizeof(mmap->size));
}
} else write_serial_string(L"No memory map.\n");
}
extern "C" void early_main(uint32_t m, uint32_t a)
{
mbi = (multiboot_info_t *)a;
vbe = (vbe_mode_info_t *)mbi->vbe_mode_info;
mem = (uint8_t *)vbe->physbase;
free_mem_start = (uint8_t*) 0x1000000;
memset(free_mem_start, 0, 0x1000000);
auto xres = vbe->Xres;
auto yres = vbe->Yres;
max_rows = yres / font.Height;
max_columns = xres / font.Width;
}
extern "C" void kernel_main(uint32_t magic, uint32_t addr)
{
wchar_t buf[10];
for (int i = 0; i < 100; ++i)
{
snprintf(buf, 10, "#%d\n", i);
draw_string(buf);
}
memcpy(mem, free_mem_start, 0x1000000);
}