Working RGB VGA output, RGB text console & bitmap fonts

This commit is contained in:
Luke Street
2018-10-07 04:21:21 -04:00
parent 594a2ffe37
commit 91039f0f36
14 changed files with 349 additions and 165 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -35,6 +35,7 @@ set(SOURCE_FILES
dwarf
stdio_impl
bmp
psf
arch/x86/mmu
drivers/ports
drivers/timer
+22 -45
View File
@@ -1,63 +1,40 @@
#include "bmp.h"
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
uint8_t *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader) {
FILE *filePtr; //our file pointer
BITMAPFILEHEADER bitmapFileHeader; //our bitmap file header
unsigned char *bitmapImage; //store image data
// int imageIdx = 0; //image index counter
// unsigned char tempRGB; //our swap variable
uint8_t *bmp_read_image(const char *filename, bmp_info_header_t *bmp_info_header) {
FILE *bmp_file;
bmp_file_header_t header;
uint8_t *img_data;
//open filename in read binary mode
filePtr = fopen(filename, "r");
if (ferror(filePtr))
bmp_file = fopen(filename, "r");
if (ferror(bmp_file))
return NULL;
//read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
//verify that this is a bmp file by check bitmap id
if (bitmapFileHeader.bfType != 0x4D42) {
fclose(filePtr);
fread(&header, sizeof(bmp_file_header_t), 1, bmp_file);
if (ferror(bmp_file) || header.type != 0x4D42) {
fclose(bmp_file);
return NULL;
}
//read the bitmap info header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
fread(bmp_info_header, sizeof(bmp_info_header_t), 1, bmp_file);
fseek(bmp_file, header.img_data_offset, SEEK_SET);
//move file point to the begging of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
printf("Image size: %Xh, offset: %Xh\n", bitmapInfoHeader->biSizeImage, bitmapFileHeader.bfOffBits);
//allocate enough memory for the bitmap image data
bitmapImage = (unsigned char *) malloc(bitmapInfoHeader->biSizeImage);
//verify memory allocation
if (!bitmapImage) {
free(bitmapImage);
fclose(filePtr);
img_data = malloc(bmp_info_header->img_data_size);
if (img_data == NULL) {
errno = ENOMEM;
free(img_data);
fclose(bmp_file);
return NULL;
}
//read in the bitmap image data
fread(bitmapImage, bitmapInfoHeader->biSizeImage, 1, filePtr);
//make sure bitmap image data was read
if (ferror(filePtr)) {
fclose(filePtr);
fread(img_data, bmp_info_header->img_data_size, 1, bmp_file);
if (ferror(bmp_file)) {
fclose(bmp_file);
return NULL;
}
//swap the r and b values to get RGB (bitmap is BGR)
// for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx += 3) {
// tempRGB = bitmapImage[imageIdx];
// bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
// bitmapImage[imageIdx + 2] = tempRGB;
// }
//close file and return bitmap iamge data
fclose(filePtr);
return bitmapImage;
fclose(bmp_file);
return img_data;
}
+20 -27
View File
@@ -2,32 +2,25 @@
#include <common.h>
typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef uint64_t QWORD;
typedef long _LONG;
typedef struct _packed bmp_file_header {
uint16_t type; //specifies the file type
uint32_t size; //specifies the size in bytes of the bitmap file
uint32_t reserved;
uint32_t img_data_offset; //species the offset in bytes from the bitmapfileheader to the bitmap bits
} bmp_file_header_t;
typedef struct _packed tagBITMAPFILEHEADER {
WORD bfType; //specifies the file type
DWORD bfSize; //specifies the size in bytes of the bitmap file
WORD bfReserved1; //reserved; must be 0
WORD bfReserved2; //reserved; must be 0
DWORD bfOffBits; //species the offset in bytes from the bitmapfileheader to the bitmap bits
} BITMAPFILEHEADER;
typedef struct _packed bmp_info_header {
uint32_t header_size; //specifies the number of bytes required by the struct
uint32_t width; //specifies width in pixels
uint32_t height; //species height in pixels
uint16_t planes; //specifies the number of color planes, must be 1
uint16_t bit_count; //specifies the number of bit per pixel
uint32_t compression;//spcifies the type of compression
uint32_t img_data_size; //size of image in bytes
uint32_t x_per_meter; //number of pixels per meter in x axis
uint32_t y_per_meter; //number of pixels per meter in y axis
uint32_t num_colors_used; //number of colors used by th ebitmap
uint32_t num_colors_important; //number of colors that are important
} bmp_info_header_t;
typedef struct _packed tagBITMAPINFOHEADER {
DWORD biSize; //specifies the number of bytes required by the struct
_LONG biWidth; //specifies width in pixels
_LONG biHeight; //species height in pixels
WORD biPlanes; //specifies the number of color planes, must be 1
WORD biBitCount; //specifies the number of bit per pixel
DWORD biCompression;//spcifies the type of compression
DWORD biSizeImage; //size of image in bytes
_LONG biXPelsPerMeter; //number of pixels per meter in x axis
_LONG biYPelsPerMeter; //number of pixels per meter in y axis
DWORD biClrUsed; //number of colors used by th ebitmap
DWORD biClrImportant; //number of colors that are important
} BITMAPINFOHEADER;
uint8_t *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader);
uint8_t *bmp_read_image(const char *filename, bmp_info_header_t *bmp_info_header);
+2 -7
View File
@@ -31,14 +31,9 @@ void console_set_serial_enabled(bool enabled) {
*/
static void knprint(const char *str, size_t len, uint8_t vga_color) {
if (vga_enabled) {
int offset = vga_get_cursor_offset();
int row = vga_get_offset_row(offset);
int col = vga_get_offset_col(offset);
int offset = -1;
for (size_t i = 0; i < len; ++i) {
offset = vga_print_char(str[i], col, row, vga_color);
row = vga_get_offset_row(offset);
col = vga_get_offset_col(offset);
offset = vga_print_char(str[i], offset, vga_color);
}
}
+191 -51
View File
@@ -1,16 +1,38 @@
#include "vga.h"
#include "ports.h"
#include "../arch/x86/mmu.h"
#include "../psf.h"
#include "../console.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include <malloc.h>
// EGA text console
uint16_t *console_fb_addr = NULL;
// RGB text console
void *rgb_fb_addr = NULL;
framebuffer_info_t rgb_fb_info = {};
psf_font_t rgb_console_font = {};
void *rgb_console_font_glyphs = NULL;
unsigned int rgb_console_rows = 0;
unsigned int rgb_console_cols = 0;
int rgb_console_offset = 0;
typedef struct rgb_console_buffer_entry {
char c;
vga_rgb_color_t fg_color;
vga_rgb_color_t bg_color;
} rgb_console_buffer_entry_t;
rgb_console_buffer_entry_t *rgb_console_buffer = NULL;
static void vga_console_repaint();
void vga_init(void *fb_addr, uint8_t type, framebuffer_info_t *fb_info) {
if (type == VGA_FB_TYPE_EGA_TEXT) {
console_fb_addr = fb_addr;
@@ -20,16 +42,59 @@ void vga_init(void *fb_addr, uint8_t type, framebuffer_info_t *fb_info) {
}
}
int vga_load_font(const char *filename) {
int prev_width = 0, prev_height = 0;
if (rgb_console_font_glyphs != NULL) {
prev_width = rgb_console_font.width;
prev_height = rgb_console_font.height;
free(rgb_console_font_glyphs);
}
rgb_console_font_glyphs = psf_read_font(filename, &rgb_console_font);
if (rgb_console_font_glyphs == NULL) {
fprintf(stderr, "Failed to read font %s (err: %d)\n", filename, errno);
return -1;
}
rgb_console_cols = rgb_fb_info.width / rgb_console_font.width;
rgb_console_rows = rgb_fb_info.height / rgb_console_font.height;
size_t buffer_size = rgb_console_rows * rgb_console_cols * sizeof(rgb_console_buffer_entry_t);
rgb_console_buffer_entry_t *new_buffer = malloc(buffer_size);
if (new_buffer == NULL) {
fprintf(stderr, "Failed to allocate memory for console buffer.\n");
return -1;
}
memset(new_buffer, 0, buffer_size);
if (rgb_console_buffer != NULL) {
size_t prev_size = (rgb_fb_info.width / prev_width)
* (rgb_fb_info.height / prev_height)
* sizeof(rgb_console_buffer_entry_t);
if (prev_size > buffer_size) {
size_t diff = prev_size - buffer_size;
memcpy(new_buffer, (void *) rgb_console_buffer + diff, buffer_size);
// FIXME refactor to avoid this kludgy division
rgb_console_offset -= diff / sizeof(rgb_console_buffer_entry_t);
} else {
memcpy(new_buffer, rgb_console_buffer, prev_size);
memset((void *) new_buffer + prev_size, 0, buffer_size - prev_size);
}
free(rgb_console_buffer);
}
rgb_console_buffer = new_buffer;
vga_console_repaint();
return 0;
}
static inline void vga_set_pixel(int x, int y, uint32_t val) {
*(uint32_t *) (rgb_fb_addr + x * 4 + rgb_fb_info.pitch * y) = val;
}
void vga_fill_rect(int x1, int y1, int x2, int y2, vga_color_t *color) {
void vga_fill_rect(int x1, int y1, int x2, int y2, vga_rgb_color_t *color) {
if (rgb_fb_addr == NULL || rgb_fb_info.bpp != 32) return;
uint32_t val = ((uint32_t) color->red << rgb_fb_info.red_field_position)
| ((uint32_t) color->green << rgb_fb_info.green_field_position)
| ((uint32_t) color->blue << rgb_fb_info.blue_field_position);
| ((uint32_t) color->green << rgb_fb_info.green_field_position)
| ((uint32_t) color->blue << rgb_fb_info.blue_field_position);
int xmin = MAX(MIN(x1, x2), 0);
int xmax = MIN(MAX(x1, x2), rgb_fb_info.width);
@@ -42,45 +107,96 @@ void vga_fill_rect(int x1, int y1, int x2, int y2, vga_color_t *color) {
}
}
void vga_display_image_bgr(int x, int y, BITMAPINFOHEADER *header, uint8_t *image) {
void vga_display_image_bgra(int x, int y, bmp_info_header_t *header, uint8_t *image) {
if (rgb_fb_addr == NULL || rgb_fb_info.bpp != 32) return;
int xmax = MIN(x + header->biWidth, rgb_fb_info.width);
int ymax = MIN(y + header->biHeight, rgb_fb_info.height);
int xmax = MIN(x + header->width, rgb_fb_info.width);
int ymax = MIN(y + header->height, rgb_fb_info.height);
for (int y1 = y; y1 < ymax; y1++) {
for (int x1 = x; x1 < xmax; x1++) {
uint8_t *pixel = image + (x1 * y1 * 4); // (header->biHeight - y1)
uint32_t val = (uint32_t) *(pixel) << rgb_fb_info.blue_field_position
| (uint32_t) *(pixel + 1) << rgb_fb_info.green_field_position
| (uint32_t) *(pixel + 2) << rgb_fb_info.red_field_position;
vga_set_pixel(x1, y1, val);
uint8_t *pixel = image + ((x1 + ((header->height - y1) * header->width)) * 4);
vga_set_pixel(x1, y1, (uint32_t) *pixel << rgb_fb_info.blue_field_position
| (uint32_t) *(pixel + 1) << rgb_fb_info.green_field_position
| (uint32_t) *(pixel + 2) << rgb_fb_info.red_field_position);
}
}
}
int vga_print_char(char c, int col, int row, char attr) {
if (console_fb_addr == NULL) return 0;
if (!attr) attr = WHITE_ON_BLACK;
static void vga_print_glyph(int offset, char c, vga_rgb_color_t *fg_color, vga_rgb_color_t *bg_color) {
if (rgb_fb_addr == NULL || rgb_fb_info.bpp != 32) return;
/* Error control: print a red 'E' if the coords aren't right */
if (col >= MAX_COLS || row >= MAX_ROWS) {
console_fb_addr[MAX_COLS * MAX_ROWS - 1] = vga_entry('E', RED_ON_WHITE);
return vga_get_offset(col, row);
int row = offset / rgb_console_cols;
int x = (offset % rgb_console_cols) * rgb_console_font.width;
int y = row * rgb_console_font.height;
uint32_t fg_val = ((uint32_t) fg_color->red << rgb_fb_info.red_field_position)
| ((uint32_t) fg_color->green << rgb_fb_info.green_field_position)
| ((uint32_t) fg_color->blue << rgb_fb_info.blue_field_position);
uint32_t bg_val = ((uint32_t) bg_color->red << rgb_fb_info.red_field_position)
| ((uint32_t) bg_color->green << rgb_fb_info.green_field_position)
| ((uint32_t) bg_color->blue << rgb_fb_info.blue_field_position);
int xmax = MIN(x + rgb_console_font.width, rgb_fb_info.width);
int ymax = MIN(y + rgb_console_font.height, rgb_fb_info.height);
uint8_t *glyph = rgb_console_font_glyphs + (rgb_console_font.bytes_per_glyph * (uint8_t) c);
for (int y1 = y; y1 < ymax; y1++) {
for (int x1 = x; x1 < xmax; x1++) {
uint8_t gb = *(glyph + (y1 - y));
vga_set_pixel(x1, y1, (gb >> (8 - (x1 - x))) & 1 ? fg_val : bg_val);
}
}
}
int vga_print_char(char c, int offset, char attr) {
if (rgb_fb_addr != NULL) {
if (rgb_console_font_glyphs == NULL) return 0;
if (offset < 0) {
offset = rgb_console_offset;
} else if (offset >= rgb_console_rows * rgb_console_cols) {
return rgb_console_offset;
}
if (c == '\b') {
offset--;
} else if (c == '\n') {
unsigned int row = offset / rgb_console_cols;
offset = (row + 1) * rgb_console_cols;
} else {
vga_rgb_color_t fg_color = {255, 255, 255};
vga_rgb_color_t bg_color = {0, 0, 0};
// FIXME make more dynamic
if (attr == RED_ON_BLACK) {
fg_color = (vga_rgb_color_t) {255, 0, 0};
bg_color = (vga_rgb_color_t) {0, 0, 0};
}
rgb_console_buffer[offset] = (rgb_console_buffer_entry_t) {c, fg_color, bg_color};
if (!c) c = ' ';
vga_print_glyph(offset++, c, &fg_color, &bg_color);
}
rgb_console_offset = offset = vga_handle_scrolling(offset);
} else if (console_fb_addr != NULL) {
if (!attr) attr = WHITE_ON_BLACK;
if (offset < 0) {
offset = vga_get_cursor_offset();
} else if (offset >= MAX_ROWS * MAX_COLS) {
console_fb_addr[MAX_COLS * MAX_ROWS - 1] = vga_entry('E', RED_ON_WHITE);
return vga_get_cursor_offset();
}
if (c == '\b') {
offset--;
} else if (c == '\n') {
offset = vga_get_offset(0, vga_get_offset_row(offset) + 1);
} else {
console_fb_addr[offset++] = ((uint16_t) attr << 8 | c);
}
vga_set_cursor_offset(offset = vga_handle_scrolling(offset));
}
int offset;
if (col >= 0 && row >= 0) offset = vga_get_offset(col, row);
else offset = vga_get_cursor_offset();
if (c == '\b') {
offset--;
} else if (c == '\n') {
row = vga_get_offset_row(offset);
offset = vga_get_offset(0, row + 1);
} else {
console_fb_addr[offset++] = ((uint16_t) attr << 8 | c);
}
vga_set_cursor_offset(offset = vga_handle_scrolling(offset));
return offset;
}
@@ -102,28 +218,52 @@ void vga_set_cursor_offset(int offset) {
}
void vga_clear_screen() {
if (console_fb_addr == NULL) return;
memset((void *) console_fb_addr, 0, MAX_COLS * MAX_ROWS * sizeof(*console_fb_addr));
vga_set_cursor_offset(vga_get_offset(0, 0));
if (console_fb_addr != NULL) {
memset(console_fb_addr, 0, MAX_COLS * MAX_ROWS * sizeof(*console_fb_addr));
vga_set_cursor_offset(vga_get_offset(0, 0));
} else if (rgb_fb_addr != NULL) {
vga_fill_rect(0, 0, rgb_fb_info.width, rgb_fb_info.height, &(vga_rgb_color_t) {0, 0, 0});
memset(rgb_console_buffer, 0, rgb_console_rows * rgb_console_cols);
rgb_console_offset = 0;
}
}
/* Advance the text cursor, scrolling the video buffer if necessary. */
int vga_handle_scrolling(int cursor_offset) {
if (console_fb_addr == NULL) return 0;
if (cursor_offset < MAX_ROWS * MAX_COLS)
return cursor_offset;
static void vga_console_repaint() {
for (size_t i = 0; i < rgb_console_rows * rgb_console_cols; ++i) {
rgb_console_buffer_entry_t *entry = &rgb_console_buffer[i];
char c = entry->c;
if (!c) c = ' '; // FIXME improve
vga_print_glyph(i, c, &entry->fg_color, &entry->bg_color);
}
}
/* Shuffle the rows back one. */
for (int i = 1; i < MAX_ROWS; i++) {
memcpy((void *) (console_fb_addr + vga_get_offset(0, i - 1)),
(void *) (console_fb_addr + vga_get_offset(0, i)),
MAX_COLS * sizeof(*console_fb_addr));
// Advance the text cursor, scrolling the video buffer if necessary.
int vga_handle_scrolling(int cursor_offset) {
if (console_fb_addr != NULL) {
if (cursor_offset < MAX_ROWS * MAX_COLS)
return cursor_offset;
for (int i = 1; i < MAX_ROWS; i++) {
memcpy(console_fb_addr + vga_get_offset(0, i - 1),
console_fb_addr + vga_get_offset(0, i),
MAX_COLS * sizeof(*console_fb_addr));
}
memset(console_fb_addr + vga_get_offset(0, MAX_ROWS - 1),
0, MAX_COLS * sizeof(*console_fb_addr));
cursor_offset -= MAX_COLS;
} else if (rgb_fb_addr != NULL) {
if (cursor_offset < rgb_console_rows * rgb_console_cols)
return cursor_offset;
size_t end_offset = (rgb_console_rows - 1) * rgb_console_cols;
memmove(rgb_console_buffer, rgb_console_buffer + rgb_console_cols,
end_offset * sizeof(rgb_console_buffer_entry_t));
memset(rgb_console_buffer + end_offset, 0, rgb_console_cols * sizeof(rgb_console_buffer_entry_t));
cursor_offset -= rgb_console_cols;
vga_console_repaint();
}
/* Blank the last line by setting all bytes to 0 */
memset((void *) (console_fb_addr + vga_get_offset(0, MAX_ROWS - 1)),
0, MAX_COLS * sizeof(*console_fb_addr));
cursor_offset -= MAX_COLS;
return cursor_offset;
}
+9 -9
View File
@@ -14,7 +14,7 @@
#define VGA_FB_TYPE_RGB 1
#define VGA_FB_TYPE_EGA_TEXT 2
struct framebuffer_info {
typedef struct framebuffer_info {
uint32_t pitch;
uint32_t width;
uint32_t height;
@@ -27,25 +27,25 @@ struct framebuffer_info {
uint8_t green_mask_size;
uint8_t blue_field_position;
uint8_t blue_mask_size;
};
typedef struct framebuffer_info framebuffer_info_t;
} framebuffer_info_t;
struct vga_color {
typedef struct vga_rgb_color {
uint8_t red;
uint8_t green;
uint8_t blue;
};
typedef struct vga_color vga_color_t;
} vga_rgb_color_t;
void vga_init(void *fb_addr, uint8_t type, framebuffer_info_t *fb_info);
void vga_fill_rect(int x1, int y1, int x2, int y2, vga_color_t *color);
int vga_load_font(const char *filename);
void vga_display_image_bgr(int x, int y, BITMAPINFOHEADER *header, uint8_t *image);
void vga_fill_rect(int x1, int y1, int x2, int y2, vga_rgb_color_t *color);
void vga_display_image_bgra(int x, int y, bmp_info_header_t *header, uint8_t *image);
// --- Console
int vga_print_char(char c, int col, int row, char attr);
int vga_print_char(char c, int offset, char attr);
int vga_handle_scrolling(int cursor_offset);
+7 -12
View File
@@ -8,13 +8,12 @@
#include "drivers/pci.h"
#include "drivers/ata.h"
#include "fatfs/ff.h"
#ifdef ENABLE_DWARF
#include "dwarf.h"
#include "bmp.h"
#include "drivers/vga.h"
#include "arch/x86/mmu.h"
#ifdef ENABLE_DWARF
#include "dwarf.h"
#endif
#include <common.h>
@@ -51,18 +50,14 @@ void kernel_main(uint32_t multiboot_magic, void *multiboot_info) {
// dwarf_find_debug_info();
#endif
console_set_vga_enabled(vga_enabled);
if (vga_enabled && !vga_load_font("assets/default8x16.psfu")) {
console_set_vga_enabled(vga_enabled);
}
clear_screen();
// FIXME add to malloc
page_table_set(0x400000, 0xC0400000, 0x83);
BITMAPINFOHEADER bmpHeader;
uint8_t *bmp = LoadBitmapFile("assets/test.bmp", &bmpHeader);
if (bmp == NULL) {
fprintf(stderr, "Failed to read bitmap");
} else {
printf("Displaying image...\n");
vga_display_image_bgr(0, 0, &bmpHeader, bmp);
}
page_table_set(0x800000, 0xC0800000, 0x83);
#ifdef KDEBUG
kprint("Initializing timer...\n");
+1 -7
View File
@@ -123,13 +123,7 @@ void multiboot_init(uint32_t magic, void *info_ptr) {
break;
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
vga_fill_rect(0, 0, 100, 100, &(vga_color_t) {255, 255, 255});
vga_fill_rect(100, 0, 200, 100, &(vga_color_t) {255, 0, 0});
vga_fill_rect(200, 0, 300, 100, &(vga_color_t) {0, 255, 0});
vga_fill_rect(300, 0, 400, 100, &(vga_color_t) {0, 0, 255});
vga_fill_rect(0, 100, 100, 200, &(vga_color_t) {255, 0, 0});
vga_fill_rect(100, 100, 200, 200, &(vga_color_t) {0, 255, 0});
vga_fill_rect(200, 100, 300, 200, &(vga_color_t) {255, 255, 255});
console_set_vga_enabled(true);
break;
default:
+39
View File
@@ -0,0 +1,39 @@
#include "psf.h"
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
void *psf_read_font(const char *filename, psf_font_t *header) {
FILE *font_file;
void *glyphs_data;
font_file = fopen(filename, "r");
if (ferror(font_file))
return NULL;
fread(header, sizeof(psf_font_t), 1, font_file);
if (ferror(font_file) || header->magic != PSF_FONT_MAGIC) {
fclose(font_file);
return NULL;
}
fseek(font_file, header->header_size, SEEK_SET);
uint32_t glyphs_size = header->bytes_per_glyph * header->num_glyph;
glyphs_data = malloc(glyphs_size);
if (glyphs_data == NULL) {
errno = ENOMEM;
free(glyphs_data);
fclose(font_file);
return NULL;
}
fread(glyphs_data, glyphs_size, 1, font_file);
if (ferror(font_file)) {
fclose(font_file);
return NULL;
}
fclose(font_file);
return glyphs_data;
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
#define PSF_FONT_MAGIC 0x864ab572
typedef struct psf_font {
uint32_t magic; // magic
uint32_t version; // zero
uint32_t header_size; // offset of bitmaps in file, 32
uint32_t flags; // 0 if there's no unicode table
uint32_t num_glyph; // number of glyphs
uint32_t bytes_per_glyph; // size of each glyph
uint32_t height; // height in pixels
uint32_t width; // width in pixels
} psf_font_t;
void *psf_read_font(const char *filename, psf_font_t *header);
+39 -7
View File
@@ -1,24 +1,26 @@
#include "shell.h"
#include "bmp.h"
#include "console.h"
#include "drivers/acpi.h"
#include "drivers/ata.h"
#include "drivers/keyboard.h"
#include "drivers/ports.h"
#include "drivers/serial.h"
#include "tests/tests.h"
#include "drivers/pci.h"
#include "drivers/pci_registry.h"
#include "drivers/ata.h"
#include "drivers/ports.h"
#include "drivers/serial.h"
#include "drivers/vga.h"
#include "elf.h"
#include "tests/tests.h"
// FIXME
#include "fatfs/ff.h"
#include <string.h>
#include <errno.h>
#include <malloc.h>
#include <vector.h>
#include <math.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <vector.h>
#define KEY_BUFFER_INITIAL_SIZE 0x100
static char *key_buffer;
@@ -220,6 +222,32 @@ static int command_exec(const char *path) {
return ret;
}
static int command_display(const char* path) {
if (!_fs_mounted) return 255;
char path_buf[512];
path_append(path_buf, curr_path, path, sizeof(path_buf));
bmp_info_header_t header;
uint8_t *bmp = bmp_read_image(path_buf, &header);
if (bmp == NULL) {
fprintf(stderr, "Failed to read bitmap");
return 1;
} else {
vga_display_image_bgra(0, 0, &header, bmp);
}
free(bmp);
return 0;
}
static int command_font(const char *path) {
if (!_fs_mounted) return 255;
char path_buf[512];
path_append(path_buf, curr_path, path, sizeof(path_buf));
return vga_load_font(path_buf) ? 1 : 0;
}
static void print_prompt(int ret) {
if (_fs_mounted) {
printf("%d %s # ", ret, curr_path);
@@ -295,6 +323,10 @@ static void shell_callback(char *input) {
ret = command_objdump(input + 8);
} else if (strncmp(input, "cat ", 4) == 0) {
ret = command_cat(input + 4);
} else if (strncmp(input, "display ", 8) == 0) {
ret = command_display(input + 8);
} else if (strncmp(input, "font ", 5) == 0) {
ret = command_font(input + 5);
} else if (strncmp(input, "./", 2) == 0) {
ret = command_exec(input + 2);
} else {