restrcuct
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
/build
|
||||||
|
|||||||
62
include/String.h
Normal file
62
include/String.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#define CUSTOM_STRING_MAX_LEN 64
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buffer[CUSTOM_STRING_MAX_LEN];
|
||||||
|
int length; // current string length, excluding null terminator
|
||||||
|
} String;
|
||||||
|
|
||||||
|
// Initialize String to empty
|
||||||
|
void cs_init(String* cs)
|
||||||
|
{
|
||||||
|
cs->buffer[0] = '\0';
|
||||||
|
cs->length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set content from a C-string (truncates if needed)
|
||||||
|
void cs_set(String* cs, const char* src)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (src[i] != '\0' && i < (CUSTOM_STRING_MAX_LEN - 1))
|
||||||
|
{
|
||||||
|
cs->buffer[i] = src[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
cs->buffer[i] = '\0';
|
||||||
|
cs->length = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare two Strings for equality
|
||||||
|
int cs_equal(const String* a, const String* b)
|
||||||
|
{
|
||||||
|
if (a->length != b->length)
|
||||||
|
return 0;
|
||||||
|
for (int i = 0; i < a->length; i++)
|
||||||
|
{
|
||||||
|
if (a->buffer[i] != b->buffer[i])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if String starts with another String prefix
|
||||||
|
int cs_starts_with(const String* cs, const String* prefix)
|
||||||
|
{
|
||||||
|
if (prefix->length > cs->length)
|
||||||
|
return 0;
|
||||||
|
for (int i = 0; i < prefix->length; i++)
|
||||||
|
{
|
||||||
|
if (cs->buffer[i] != prefix->buffer[i])
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append a char to String (ignores if full)
|
||||||
|
void cs_append_char(String* cs, char c)
|
||||||
|
{
|
||||||
|
if (cs->length < (CUSTOM_STRING_MAX_LEN - 1))
|
||||||
|
{
|
||||||
|
cs->buffer[cs->length++] = c;
|
||||||
|
cs->buffer[cs->length] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
1882
include/bitmapfont.h
Normal file
1882
include/bitmapfont.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
#ifndef FONT_PACK_H
|
#ifndef FONT_PACK_H
|
||||||
#define FONT_PACK_H
|
#define FONT_PACK_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
46
include/renderer_common.h
Normal file
46
include/renderer_common.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef RENDERER_COMMON_H
|
||||||
|
#define RENDERER_COMMON_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define FONT_WIDTH 16
|
||||||
|
#define FONT_HEIGHT 16
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int x, y;
|
||||||
|
unsigned int color;
|
||||||
|
} RenderBase;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
RenderBase base;
|
||||||
|
const char *text;
|
||||||
|
void *font; // Opaque font pointer
|
||||||
|
} RenderText;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int x, y;
|
||||||
|
unsigned int width, height;
|
||||||
|
unsigned int color;
|
||||||
|
} RenderObject;
|
||||||
|
|
||||||
|
typedef struct Renderer Renderer;
|
||||||
|
|
||||||
|
struct Renderer {
|
||||||
|
volatile unsigned int *fb;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned int pitch;
|
||||||
|
|
||||||
|
bool (*init)(Renderer *renderer);
|
||||||
|
|
||||||
|
void (*clear_screen)(Renderer *renderer, unsigned int color);
|
||||||
|
void (*draw_text)(Renderer *renderer, RenderText *text_obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the framebuffer (common across both renderers)
|
||||||
|
*/
|
||||||
|
bool renderer_init_common(Renderer *renderer);
|
||||||
|
|
||||||
|
#endif // RENDERER_COMMON_H
|
||||||
11
makefile
11
makefile
@@ -6,17 +6,17 @@ AS = $(CROSS)as
|
|||||||
LD = $(CROSS)ld
|
LD = $(CROSS)ld
|
||||||
OBJCOPY = $(CROSS)objcopy
|
OBJCOPY = $(CROSS)objcopy
|
||||||
|
|
||||||
CFLAGS = -O2 -ffreestanding -nostdlib -Wall -Wextra
|
CFLAGS = -O2 -ffreestanding -nostdlib -Wall -Wextra -Iinclude include/
|
||||||
LDFLAGS = -T src/linker.ld
|
LDFLAGS = -T src/boot/linker.ld
|
||||||
|
|
||||||
SRC = src
|
SRC = src
|
||||||
BUILD = build
|
BUILD = build
|
||||||
|
|
||||||
# List all C source files here (update as needed)
|
# List all C source files here (update as needed)
|
||||||
SOURCES_C = $(SRC)/renderer.c $(SRC)/font_pack.c $(SRC)/main.c
|
SOURCES_C = $(SRC)/renderer.c $(SRC)/font_pack.c $(SRC)/main.c
|
||||||
|
|
||||||
# List assembler source files
|
# List assembler source files
|
||||||
SOURCES_ASM = $(SRC)/boot.s
|
SOURCES_ASM = $(SRC)/boot/boot.s
|
||||||
|
|
||||||
# Object files (one per source file)
|
# Object files (one per source file)
|
||||||
OBJ_C = $(patsubst $(SRC)/%.c,$(BUILD)/%.o,$(SOURCES_C))
|
OBJ_C = $(patsubst $(SRC)/%.c,$(BUILD)/%.o,$(SOURCES_C))
|
||||||
@@ -32,6 +32,7 @@ all: $(TARGET_IMG)
|
|||||||
# Create build directory if it does not exist
|
# Create build directory if it does not exist
|
||||||
$(BUILD):
|
$(BUILD):
|
||||||
mkdir -p $(BUILD)
|
mkdir -p $(BUILD)
|
||||||
|
mkdir -p $(BUILD)/boot
|
||||||
|
|
||||||
# Assemble assembly sources
|
# Assemble assembly sources
|
||||||
$(BUILD)/%.o: $(SRC)/%.s | $(BUILD)
|
$(BUILD)/%.o: $(SRC)/%.s | $(BUILD)
|
||||||
@@ -54,4 +55,4 @@ clean:
|
|||||||
|
|
||||||
# Run QEMU emulator for Raspberry Pi 3 with serial output redirected to terminal
|
# Run QEMU emulator for Raspberry Pi 3 with serial output redirected to terminal
|
||||||
run: $(TARGET_IMG)
|
run: $(TARGET_IMG)
|
||||||
sudo qemu-system-aarch64 -M raspi3b -serial stdio -kernel $(TARGET_IMG)
|
qemu-system-aarch64 -M raspi3b -serial stdio -kernel $(TARGET_IMG)
|
||||||
|
|||||||
2280
src/font_pack.c
2280
src/font_pack.c
File diff suppressed because it is too large
Load Diff
71
src/main.c
71
src/main.c
@@ -2,9 +2,30 @@
|
|||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "font_pack.h"
|
#include "font_pack.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
|
static void delay_1s(void)
|
||||||
|
{
|
||||||
|
volatile unsigned long count = 80000000; // Example for ~1 sec at ~80 MHz CPU
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
__asm__ volatile("nop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void delay_seconds(unsigned int seconds)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < seconds; i++)
|
||||||
|
{
|
||||||
|
delay_1s();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int kernel_main(void)
|
int kernel_main(void)
|
||||||
{
|
{
|
||||||
|
String str;
|
||||||
|
cs_init(&str);
|
||||||
|
cs_set(&str, "HELLO MARIO");
|
||||||
uart_io.puts("Initializing renderer...\n");
|
uart_io.puts("Initializing renderer...\n");
|
||||||
|
|
||||||
Renderer renderer;
|
Renderer renderer;
|
||||||
@@ -23,48 +44,38 @@ int kernel_main(void)
|
|||||||
uart_io.putc('\n');
|
uart_io.putc('\n');
|
||||||
|
|
||||||
RenderObject background = {0, 0, renderer.width, renderer.height, COLOR_RED};
|
RenderObject background = {0, 0, renderer.width, renderer.height, COLOR_RED};
|
||||||
RenderObject blue_rect = {100, 100, 100, 100, COLOR_BLUE};
|
|
||||||
|
|
||||||
RenderText text = {
|
RenderText text = {
|
||||||
.base = {
|
.base = {
|
||||||
.x = 20,
|
.x = 20,
|
||||||
.y = 30,
|
.y = 30,
|
||||||
.color = 0xFFFFFFFF},
|
.color = 0xFFFFFFFF},
|
||||||
.text = "HELLO MARIO",
|
.text = str.buffer,
|
||||||
.font = &basic_font_pack,
|
.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)
|
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.clear_screen(&renderer, background.color);
|
||||||
renderer.draw_rect(&renderer, &blue_rect);
|
|
||||||
renderer.draw_text(&renderer, &text);
|
renderer.draw_text(&renderer, &text);
|
||||||
|
|
||||||
// Print updated position
|
char c = uart_getc();
|
||||||
uart_io.puts("\nRect X: ");
|
|
||||||
uart_io.print_int(blue_rect.x);
|
if (c >= 32 && c <= 126) // Printable ASCII
|
||||||
uart_io.puts(" Y: ");
|
{
|
||||||
uart_io.print_int(blue_rect.y);
|
cs_append_char(&str, c);
|
||||||
uart_io.putc('\n');
|
}
|
||||||
|
else if (c == '\b' || c == 127) // Backspace support
|
||||||
|
{
|
||||||
|
if (str.length > 0)
|
||||||
|
{
|
||||||
|
str.length--;
|
||||||
|
str.buffer[str.length] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_puts(str.buffer);
|
||||||
|
renderer.draw_text(&renderer, &text);
|
||||||
|
|
||||||
|
delay_seconds(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user