This commit is contained in:
2025-11-10 16:02:04 -07:00
parent 9b52fa9722
commit e148177bbd
11 changed files with 1045 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.DS_Store

57
makefile Executable file
View File

@@ -0,0 +1,57 @@
CROSS = aarch64-none-elf-
CC = $(CROSS)gcc
AS = $(CROSS)as
LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
CFLAGS = -O2 -ffreestanding -nostdlib -Wall -Wextra
LDFLAGS = -T src/linker.ld
SRC = src
BUILD = build
# List all C source files here (update as needed)
SOURCES_C = $(SRC)/renderer.c $(SRC)/font_pack.c $(SRC)/main.c
# List assembler source files
SOURCES_ASM = $(SRC)/boot.s
# Object files (one per source file)
OBJ_C = $(patsubst $(SRC)/%.c,$(BUILD)/%.o,$(SOURCES_C))
OBJ_ASM = $(patsubst $(SRC)/%.s,$(BUILD)/%.o,$(SOURCES_ASM))
TARGET_ELF = $(BUILD)/kernel.elf
TARGET_IMG = $(BUILD)/kernel8.img
.PHONY: all clean run
all: $(TARGET_IMG)
# Create build directory if it does not exist
$(BUILD):
mkdir -p $(BUILD)
# Assemble assembly sources
$(BUILD)/%.o: $(SRC)/%.s | $(BUILD)
$(AS) $< -o $@
# Compile C sources
$(BUILD)/%.o: $(SRC)/%.c | $(BUILD)
$(CC) $(CFLAGS) -c $< -o $@
# Link all object files into ELF kernel
$(TARGET_ELF): $(OBJ_ASM) $(OBJ_C)
$(LD) $(LDFLAGS) $^ -o $@
# Convert ELF to raw binary image
$(TARGET_IMG): $(TARGET_ELF)
$(OBJCOPY) $< -O binary $@
clean:
rm -rf $(BUILD)
# Run QEMU emulator for Raspberry Pi 3 with serial output redirected to terminal
run: $(TARGET_IMG)
sudo qemu-system-aarch64 -M raspi3b -serial stdio -kernel $(TARGET_IMG)

17
src/boot.s Normal file
View File

@@ -0,0 +1,17 @@
.section .text
.global _start
_start:
ldr x0, =stack_top
mov sp, x0
bl kernel_main
1:
b 1b
.section .bss
.align 3
.global stack_top
stack_top:
.skip 0x8000 // 32 KB stack

27
src/color.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef COLOR_H
#define COLOR_H
// Color format: 0xAABBGGRR (BGRA32 - little endian)
#define COLOR_BLACK 0xFF000000
#define COLOR_WHITE 0xFFFFFFFF
#define COLOR_RED 0xFF0000FF
#define COLOR_GREEN 0xFF00FF00
#define COLOR_BLUE 0xFFFF0000
#define COLOR_YELLOW 0xFF00FFFF
#define COLOR_CYAN 0xFFFFFF00
#define COLOR_MAGENTA 0xFFFF00FF
#define COLOR_GRAY 0xFF808080
#define COLOR_ORANGE 0xFF00A5FF
#define COLOR_BROWN 0xFF2A2AA5
#define COLOR_PURPLE 0xFF800080
#define COLOR_PINK 0xFFCBC0FF
#define COLOR_LIME 0xFF00FFBF
#define COLOR_NAVY 0xFF800000
#define COLOR_TEAL 0xFF808000
#define COLOR_OLIVE 0xFF008080
// For custom BGR colors
#define BGR(r, g, b) (0xFF000000 | ((b) << 16) | ((g) << 8) | (r))
#endif // COLOR_H

544
src/font_pack.c Normal file
View File

@@ -0,0 +1,544 @@
#include "font_pack.h"
// Letter A: Thickened diagonals and vertical legs
static const uint8_t letter_A_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00011100, // ** ***
0b00111000, 0b00011100, // ** ***
0b01110000, 0b00001110, //*** ***
0b01110000, 0b00001110, //*** ***
0b11111111, 0b11111111, //************
0b11111111, 0b11111111, //************
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b00000000, 0b00000000, //
};
// Letter B: Thickened vertical and horizontal strokes
static const uint8_t letter_B_16x16[32] = {
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter C: Thickened curves
static const uint8_t letter_C_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter D: Thickened vertical and curved strokes
static const uint8_t letter_D_16x16[32] = {
0b11111111, 0b11000000, //********
0b11111111, 0b11000000, //********
0b11100000, 0b01100000, //*** **
0b11100000, 0b01100000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b00110000, //*** **
0b11100000, 0b01100000, //*** **
0b11100000, 0b01100000, //*** **
0b11111111, 0b11000000, //********
0b11111111, 0b11000000, //********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter E: Thickened horizontal and vertical strokes
static const uint8_t letter_E_16x16[32] = {
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter F: Thickened horizontal and vertical strokes
static const uint8_t letter_F_16x16[32] = {
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter G: Thickened curves and horizontal bar
static const uint8_t letter_G_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00111111, 0b11100000, // *** ****
0b00111111, 0b11100000, // *** ****
0b00111000, 0b01110000, // *** ***
0b00111000, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter H: Thickened vertical and horizontal bars
static const uint8_t letter_H_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11111111, 0b11111111, //************
0b11111111, 0b11111111, //************
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter I: Thickened vertical and horizontal bars
static const uint8_t letter_I_16x16[32] = {
0b00001111, 0b11110000, // ******
0b00001111, 0b11110000, // ******
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00001111, 0b11110000, // ******
0b00001111, 0b11110000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter J: Thickened vertical and curved strokes
static const uint8_t letter_J_16x16[32] = {
0b00000000, 0b01111000, // ****
0b00000000, 0b01111000, // ****
0b00000000, 0b00111000, // ***
0b00000000, 0b00111000, // ***
0b00000000, 0b00111000, // ***
0b00000000, 0b00111000, // ***
0b00000000, 0b00111000, // ***
0b00000000, 0b00111000, // ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b01111111, 0b11110000, // ********
0b01111111, 0b11110000, // ********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter K: Thickened vertical and diagonal strokes
static const uint8_t letter_K_16x16[32] = {
0b11100000, 0b01100000, //*** **
0b11100000, 0b01100000, //*** **
0b11100000, 0b11000000, //*** *
0b11100000, 0b11000000, //*** *
0b11100111, 0b00000000, //*** ***
0b11100111, 0b00000000, //*** ***
0b11111100, 0b00000000, //**** *
0b11111100, 0b00000000, //**** *
0b11111000, 0b00000000, //**** *
0b11111000, 0b00000000, //**** *
0b11111100, 0b00000000, //**** *
0b11111100, 0b00000000, //**** *
0b11101100, 0b00000000, //*** **
0b11101100, 0b00000000, //*** **
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter L: Thickened vertical and horizontal strokes
static const uint8_t letter_L_16x16[32] = {
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter M: Thickened vertical and diagonal strokes
static const uint8_t letter_M_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11110000, 0b00011110, //**** ****
0b11110000, 0b00011110, //**** ****
0b11111000, 0b00111110, //**** *****
0b11111000, 0b00111110, //**** *****
0b11101100, 0b01101110, //*** ** ***
0b11101100, 0b01101110, //*** ** ***
0b11100110, 0b11001110, //*** *** ***
0b11100110, 0b11001110, //*** *** ***
0b11100011, 0b10001110, //*** ** ***
0b11100011, 0b10001110, //*** ** ***
0b11100001, 0b00001110, //*** ***
0b11100001, 0b00001110, //*** ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter N: Thickened vertical and diagonal strokes
static const uint8_t letter_N_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11110000, 0b00001110, //**** ***
0b11110000, 0b00001110, //**** ***
0b11111000, 0b00001110, //**** ***
0b11111000, 0b00001110, //**** ***
0b11101100, 0b00001110, //*** * ***
0b11101100, 0b00001110, //*** * ***
0b11100110, 0b00001110, //*** * ***
0b11100110, 0b00001110, //*** * ***
0b11100011, 0b00001110, //*** * ***
0b11100011, 0b00001110, //*** * ***
0b11100001, 0b00001110, //*** ***
0b11100001, 0b00001110, //*** ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter O: Thickened curves
static const uint8_t letter_O_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter P: Thickened vertical and horizontal strokes
static const uint8_t letter_P_16x16[32] = {
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b11100000, 0b00000000, //***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter Q: Thickened curves and diagonal tail
static const uint8_t letter_Q_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111000, 0b00011100, // *** ***
0b00111010, 0b00111000, // *** ***
0b00111001, 0b01110000, // *** ***
0b00111000, 0b11100000, // *** ***
0b00011111, 0b11000000, // **** *
0b00011111, 0b11000000, // **** *
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter R: Thickened vertical, horizontal, and diagonal strokes
static const uint8_t letter_R_16x16[32] = {
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11100000, 0b00111000, //*** ***
0b11111111, 0b11100000, //*********
0b11111111, 0b11100000, //*********
0b11100000, 0b11000000, //*** *
0b11100000, 0b11000000, //*** *
0b11100000, 0b01100000, //*** *
0b11100000, 0b00110000, //*** *
0b11100000, 0b00011000, //*** *
0b11100000, 0b00001100, //*** *
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter S: Thickened curves
static const uint8_t letter_S_16x16[32] = {
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00011100, 0b01110000, // *** ***
0b00011100, 0b01110000, // *** ***
0b00111000, 0b00000000, // ***
0b00111000, 0b00000000, // ***
0b00001111, 0b11100000, // ******
0b00001111, 0b11100000, // ******
0b00000000, 0b01110000, // ***
0b00000000, 0b01110000, // ***
0b00000000, 0b01110000, // ***
0b00111000, 0b00011100, // *** ***
0b00011111, 0b11100000, // ******
0b00011111, 0b11100000, // ******
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter T: Thickened horizontal and vertical strokes
static const uint8_t letter_T_16x16[32] = {
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter U: Thickened vertical and curved strokes
static const uint8_t letter_U_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b01111111, 0b11111000, // *********
0b01111111, 0b11111000, // *********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter V: Thickened diagonal strokes
static const uint8_t letter_V_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b01110000, 0b00011100, // ** ***
0b01110000, 0b00011100, // ** ***
0b00111000, 0b00111000, // ** ***
0b00111000, 0b00111000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00000111, 0b11000000, // ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter W: Thickened vertical and diagonal strokes
static const uint8_t letter_W_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b11100111, 0b00011100, //*** ***
0b11100111, 0b00011100, //*** ***
0b11101110, 0b00111000, //*** ***
0b11101110, 0b00111000, //*** ***
0b11111100, 0b01110000, //**** ***
0b11111100, 0b01110000, //**** ***
0b11111000, 0b11100000, //**** ***
0b11111000, 0b11100000, //**** ***
0b11111100, 0b11000000, //***** **
0b11111100, 0b11000000, //***** **
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter X: Thickened diagonal strokes
static const uint8_t letter_X_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b01110000, 0b00011100, // ** ***
0b01110000, 0b00011100, // ** ***
0b00111000, 0b00111000, // ** ***
0b00111000, 0b00111000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00011100, 0b01110000, // ** ***
0b00011100, 0b01110000, // ** ***
0b01110000, 0b00011100, // ** ***
0b01110000, 0b00011100, // ** ***
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter Y: Thickened diagonal and vertical strokes
static const uint8_t letter_Y_16x16[32] = {
0b11100000, 0b00001110, //*** ***
0b11100000, 0b00001110, //*** ***
0b01110000, 0b00011100, // ** ***
0b01110000, 0b00011100, // ** ***
0b00111000, 0b00111000, // ** ***
0b00111000, 0b00111000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00011100, 0b01110000, // ** ***
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00001110, 0b11100000, // ** **
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Letter Z: Thickened horizontal and diagonal strokes
static const uint8_t letter_Z_16x16[32] = {
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b00000000, 0b11100000, // ***
0b00000000, 0b11100000, // ***
0b00000001, 0b11000000, // **
0b00000001, 0b11000000, // **
0b00000011, 0b10000000, // **
0b00000011, 0b10000000, // **
0b00000111, 0b00000000, // ***
0b00000111, 0b00000000, // ***
0b00001110, 0b00000000, // ***
0b00001110, 0b00000000, // ***
0b11111111, 0b11111000, //***********
0b11111111, 0b11111000, //***********
0b00000000, 0b00000000, //
0b00000000, 0b00000000, //
};
// Font bitmaps array
static const uint8_t *font_bitmaps_16x16[26] = {
letter_A_16x16, letter_B_16x16, letter_C_16x16, letter_D_16x16, letter_E_16x16,
letter_F_16x16, letter_G_16x16, letter_H_16x16, letter_I_16x16, letter_J_16x16,
letter_K_16x16, letter_L_16x16, letter_M_16x16, letter_N_16x16, letter_O_16x16,
letter_P_16x16, letter_Q_16x16, letter_R_16x16, letter_S_16x16, letter_T_16x16,
letter_U_16x16, letter_V_16x16, letter_W_16x16, letter_X_16x16, letter_Y_16x16,
letter_Z_16x16
};
// Font pack structure
const FontPack basic_font_pack = {
.bitmaps = {
letter_A_16x16, letter_B_16x16, letter_C_16x16, letter_D_16x16, letter_E_16x16,
letter_F_16x16, letter_G_16x16, letter_H_16x16, letter_I_16x16, letter_J_16x16,
letter_K_16x16, letter_L_16x16, letter_M_16x16, letter_N_16x16, letter_O_16x16,
letter_P_16x16, letter_Q_16x16, letter_R_16x16, letter_S_16x16, letter_T_16x16,
letter_U_16x16, letter_V_16x16, letter_W_16x16, letter_X_16x16, letter_Y_16x16,
letter_Z_16x16
}
};

22
src/font_pack.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef FONT_PACK_H
#define FONT_PACK_H
#include <stdint.h>
#define FONT_WIDTH 16
#define FONT_HEIGHT 16
#define FONT_BITMAP_SIZE ((FONT_WIDTH * FONT_HEIGHT) / 8) // 32 bytes per character
static const uint8_t empty_char_16x16[32] = {0};
typedef struct {
const uint8_t *bitmaps[26]; // Pointers to each 16x16 bitmap
} FontPack;
extern const FontPack basic_font_pack;
static inline const uint8_t *font_get_char_bitmap(const FontPack *pack, char c) {
if (c >= 'A' && c <= 'Z')
return pack->bitmaps[c - 'A'];
return empty_char_16x16; // Or point to empty_char_16x16
}
#endif // FONT_PACK_H

64
src/io.h Normal file
View File

@@ -0,0 +1,64 @@
#ifndef UART_IO_H
#define UART_IO_H
#include <stdint.h>
#define UART0_BASE 0x3F201000
#define UART0_DR (*((volatile uint32_t *)(UART0_BASE + 0x00)))
#define UART0_FR (*((volatile uint32_t *)(UART0_BASE + 0x18)))
typedef struct UART_IO {
void (*putc)(char c);
void (*puts)(const char* str);
char (*getc)(void);
void (*print_int)(unsigned int value);
} UART_IO;
// Function implementations
static void uart_putc(char c)
{
while (UART0_FR & (1 << 5)) { } // Wait while TXFF is set
UART0_DR = c;
}
static void uart_puts(const char* str)
{
while (*str)
uart_putc(*str++);
}
static char uart_getc(void)
{
while (UART0_FR & (1 << 4)) { } // Wait while RXFE is set
return (char)(UART0_DR & 0xFF);
}
static void uart_print_int(unsigned int value)
{
char buffer[10];
int i = 0;
if (value == 0) {
uart_putc('0');
return;
}
while (value > 0 && i < 10) {
buffer[i++] = (value % 10) + '0';
value /= 10;
}
while (i--)
uart_putc(buffer[i]);
}
// UART_IO instance with function pointers assigned
static const UART_IO uart_io = {
.putc = uart_putc,
.puts = uart_puts,
.getc = uart_getc,
.print_int = uart_print_int,
};
#endif // UART_IO_H

10
src/linker.ld Normal file
View File

@@ -0,0 +1,10 @@
ENTRY(_start)
SECTIONS {
. = 0x80000;
.text : { *(.text*) }
.rodata : { *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) }
. = ALIGN(8);
stack_top = . + 0x8000;
}

70
src/main.c Normal file
View File

@@ -0,0 +1,70 @@
#include "renderer.h"
#include "color.h"
#include "font_pack.h"
#include "io.h"
int kernel_main(void)
{
uart_io.puts("Initializing renderer...\n");
Renderer renderer;
if (!renderer_init(&renderer))
{
uart_io.puts("Failed to allocate framebuffer.\n");
while (1)
;
}
uart_io.puts("Framebuffer allocated.\n");
uart_io.puts("Width: ");
uart_io.print_int(renderer.width);
uart_io.puts("\nHeight: ");
uart_io.print_int(renderer.height);
uart_io.putc('\n');
RenderObject background = {0, 0, renderer.width, renderer.height, COLOR_RED};
RenderObject blue_rect = {100, 100, 100, 100, COLOR_BLUE};
RenderText text = {
.base = {
.x = 20,
.y = 30,
.color = 0xFFFFFFFF},
.text = "HELLO MARIO",
.font = &basic_font_pack,
};
uart_io.puts("Use WASD keys to move the rectangle.\n");
// Initial draw
renderer.clear_screen(&renderer, background.color);
renderer.draw_rect(&renderer, &blue_rect);
renderer.draw_text(&renderer, &text);
while (1)
{
char c = uart_io.getc();
uart_io.putc(c);
// Movement
if ((c == 'w' || c == 'W') && blue_rect.y > 0)
blue_rect.y = (blue_rect.y > 10) ? blue_rect.y - 10 : 0;
if ((c == 's' || c == 'S') && (blue_rect.y + blue_rect.height) < renderer.height)
blue_rect.y += 10;
if ((c == 'a' || c == 'A') && blue_rect.x > 0)
blue_rect.x = (blue_rect.x > 10) ? blue_rect.x - 10 : 0;
if ((c == 'd' || c == 'D') && (blue_rect.x + blue_rect.width) < renderer.width)
blue_rect.x += 10;
// Redraw everything
renderer.clear_screen(&renderer, background.color);
renderer.draw_rect(&renderer, &blue_rect);
renderer.draw_text(&renderer, &text);
// Print updated position
uart_io.puts("\nRect X: ");
uart_io.print_int(blue_rect.x);
uart_io.puts(" Y: ");
uart_io.print_int(blue_rect.y);
uart_io.putc('\n');
}
}

174
src/renderer.c Normal file
View File

@@ -0,0 +1,174 @@
#include "renderer.h"
#include "font_pack.h"
#define MBOX_CH_PROP 8
#define MBOX_BASE 0x3F00B880
volatile unsigned int __attribute__((aligned(16))) mbox[36];
// Small delay loop
static inline void delay(int n)
{
while (n--)
__asm__ volatile("nop");
}
// Mailbox call function for communication with GPU
unsigned int mailbox_call(unsigned int channel)
{
unsigned int r = ((unsigned int)((unsigned long)&mbox) & ~0xF) | (channel & 0xF);
// Wait until mailbox not full
while (*(volatile unsigned int *)(MBOX_BASE + 0x18) & 0x80000000)
delay(100);
// Write the channel combined with mailbox address
*(volatile unsigned int *)(MBOX_BASE + 0x20) = r;
while (1)
{
// Wait for response
while (*(volatile unsigned int *)(MBOX_BASE + 0x18) & 0x40000000)
delay(100);
// Check if response is for our message
if (*(volatile unsigned int *)(MBOX_BASE + 0x00) == r)
{
// Return true if response is successful
return mbox[1] == 0x80000000;
}
}
}
void draw_text_impl(Renderer *renderer, RenderText *text_obj) {
if (!renderer || !text_obj || !text_obj->text || !text_obj->font) {
return; // Invalid inputs
}
unsigned int x0 = text_obj->base.x;
unsigned int y0 = text_obj->base.y;
unsigned int color = text_obj->base.color;
const char *str = text_obj->text;
// For each character in string
for (const char *p = str; *p != '\0'; p++) {
unsigned char c = (unsigned char)*p; // Ensure unsigned char for safety
// Get bitmap (guaranteed non-NULL due to empty_char_16x16 fallback)
const uint8_t *bitmap = font_get_char_bitmap(text_obj->font, c);
// Draw this single character (16x16)
for (unsigned int y = 0; y < FONT_HEIGHT; y++) {
// Read two bytes separately to avoid alignment issues
uint16_t row = ((uint16_t)bitmap[y * 2] << 8) | bitmap[y * 2 + 1];
for (unsigned int bit = 0; bit < FONT_WIDTH; bit++) {
if (row & (1 << (15 - bit))) { // Check 16 bits, MSB first
unsigned int px = x0 + bit;
unsigned int py = y0 + y;
if (px < renderer->width && py < renderer->height) {
// Assume 32-bit pixels; pitch in bytes
unsigned int *pixel = &renderer->fb[py * (renderer->pitch / 4) + px];
*pixel = color;
}
}
}
}
// Advance x for next char
x0 += FONT_WIDTH + 1;
}
}
// Initialize the framebuffer via mailbox property channel
bool renderer_init(Renderer *renderer)
{
mbox[0] = 35 * 4; // Buffer size in bytes
mbox[1] = 0; // Request
// Set physical width and height
mbox[2] = 0x48003;
mbox[3] = 8;
mbox[4] = 8;
mbox[5] = 640;
mbox[6] = 480;
// Set virtual width and height
mbox[7] = 0x48004;
mbox[8] = 8;
mbox[9] = 8;
mbox[10] = 640;
mbox[11] = 480;
// Set depth (bits per pixel)
mbox[12] = 0x48005;
mbox[13] = 4;
mbox[14] = 4;
mbox[15] = 32;
// Allocate framebuffer
mbox[16] = 0x40001;
mbox[17] = 8;
mbox[18] = 8;
mbox[19] = 16; // alignment
mbox[20] = 0;
// Get pitch
mbox[21] = 0x40008;
mbox[22] = 4;
mbox[23] = 4;
mbox[24] = 0;
// End tag
mbox[25] = 0;
if (!mailbox_call(MBOX_CH_PROP))
return false;
renderer->width = mbox[5];
renderer->height = mbox[6];
renderer->pitch = mbox[24];
renderer->fb = (volatile unsigned int *)(mbox[19] & 0x3FFFFFFF);
renderer->clear_screen = clear_screen_impl;
renderer->draw_rect = draw_rect_impl;
renderer->draw_text = draw_text_impl;
renderer->draw_objects = draw_objects_impl;
return true;
}
// Render function implementations
void clear_screen_impl(Renderer *renderer, unsigned int color)
{
for (unsigned int y = 0; y < renderer->height; y++)
{
for (unsigned int x = 0; x < renderer->width; x++)
{
renderer->fb[y * (renderer->pitch / 4) + x] = color;
}
}
}
void draw_rect_impl(Renderer *renderer, RenderObject *obj)
{
unsigned int max_y = obj->y + obj->height;
unsigned int max_x = obj->x + obj->width;
if (max_y > renderer->height)
max_y = renderer->height;
if (max_x > renderer->width)
max_x = renderer->width;
for (unsigned int y = obj->y; y < max_y; y++)
{
for (unsigned int x = obj->x; x < max_x; x++)
{
renderer->fb[y * (renderer->pitch / 4) + x] = obj->color;
}
}
}
void draw_objects_impl(Renderer *renderer, RenderObject *objs[], unsigned int count)
{
for (unsigned int i = 0; i < count; i++)
{
draw_rect_impl(renderer, objs[i]);
}
}

59
src/renderer.h Normal file
View File

@@ -0,0 +1,59 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <stddef.h>
#include <stdbool.h>
#include "font_pack.h"
typedef struct RenderObject {
unsigned int x, y;
unsigned int width, height;
unsigned int color;
} RenderObject;
typedef struct RenderText {
RenderObject base; // Position, size, color
const char *text; // String to render
const FontPack *font; // Font used for rendering
} RenderText;
typedef struct Renderer {
volatile unsigned int *fb;
unsigned int width;
unsigned int height;
unsigned int pitch;
void (*clear_screen)(struct Renderer *renderer, unsigned int color);
void (*draw_rect)(struct Renderer *renderer, RenderObject *obj);
void (*draw_text)(struct Renderer *renderer, RenderText *text);
void (*draw_objects)(struct Renderer *renderer, RenderObject *objs[], unsigned int count);
} Renderer;
// ===== Window definition =====
typedef struct Window {
RenderObject frame; // Outer frame of the window
RenderObject content_area; // Area inside window (excluding titlebar)
RenderText title_bar; // Title bar text
unsigned int background_color; // Background fill color for content
bool visible; // Visibility flag
} Window;
// Function to initialize a Window
void window_init(Window *win,
unsigned int x, unsigned int y,
unsigned int width, unsigned int height,
const char *title, const FontPack *font,
unsigned int title_color, unsigned int bg_color,
unsigned int text_color);
// Function to render the Window
void window_draw(Renderer *renderer, Window *win);
// ===== Renderer functions =====
bool renderer_init(Renderer *renderer);
void clear_screen_impl(Renderer *renderer, unsigned int color);
void draw_rect_impl(Renderer *renderer, RenderObject *obj);
void draw_text_impl(Renderer *renderer, RenderText *text);
void draw_objects_impl(Renderer *renderer, RenderObject *objs[], unsigned int count);
#endif // RENDERER_H