Complete overhaul of the Legacy system.

Now with reasonable architecture, plus added x86_64.
This commit is contained in:
Curle 2020-02-06 20:20:58 +00:00
commit 822cfc4b9e
20 changed files with 2405 additions and 0 deletions

View File

@ -0,0 +1,108 @@
#ifndef _BOOTLOADER_H_
#define _BOOTLOADER_H_
#ifdef __cplusplus
extern "C" {
#endif
#define BOOT_MAGIC "BOOT"
/* minimum protocol level:
* hardcoded kernel name, static kernel memory addresses */
#define PROTOCOL_MINIMAL 0
/* static protocol level:
* kernel name parsed from environment, static kernel memory addresses */
#define PROTOCOL_STATIC 1
/* dynamic protocol level:
* kernel name parsed, kernel memory addresses from ELF or PE symbols */
#define PROTOCOL_DYNAMIC 2
/* big-endian flag */
#define PROTOCOL_BIGENDIAN 0x80
/* loader types, just informational */
#define LOADER_BIOS (0<<2)
#define LOADER_UEFI (1<<2)
#define LOADER_RPI (2<<2)
/* framebuffer pixel format, only 32 bits supported */
#define FB_ARGB 0
#define FB_RGBA 1
#define FB_ABGR 2
#define FB_BGRA 3
/* mmap entry, type is stored in least significant tetrad (half byte) of size
* this means size described in 16 byte units (not a problem, most modern
* firmware report memory in pages, 4096 byte units anyway). */
typedef struct {
uint64_t ptr;
uint64_t size;
} __attribute__((packed)) MMapEnt;
#define MMapEnt_Ptr(a) (a->ptr)
#define MMapEnt_Size(a) (a->size & 0xFFFFFFFFFFFFFFF0)
#define MMapEnt_Type(a) (a->size & 0xF)
#define MMapEnt_IsFree(a) ((a->size&0xF)==1)
#define MMAP_USED 0 /* don't use. Reserved or unknown regions */
#define MMAP_FREE 1 /* usable memory */
#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */
#define MMAP_MMIO 3 /* memory mapped IO region */
#define INITRD_MAXSIZE 16 /* Mb */
typedef struct {
/* first 64 bytes is platform independent */
uint8_t magic[4]; /* 'BOOT' magic */
uint32_t size; /* length of bootboot structure, minimum 128 */
uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */
uint8_t fb_type; /* framebuffer type, see FB_* above */
uint16_t numcores; /* number of processor cores */
uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */
int16_t timezone; /* in minutes -1440..1440 */
uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */
uint64_t initrd_ptr; /* ramdisk image position and size */
uint64_t initrd_size;
uint8_t *fb_ptr; /* framebuffer pointer and dimensions */
uint32_t fb_size;
uint32_t fb_width;
uint32_t fb_height;
uint32_t fb_scanline;
/* the rest (64 bytes) is platform specific */
union {
struct {
uint64_t acpi_ptr;
uint64_t smbi_ptr;
uint64_t efi_ptr;
uint64_t mp_ptr;
uint64_t unused0;
uint64_t unused1;
uint64_t unused2;
uint64_t unused3;
} x86_64;
struct {
uint64_t acpi_ptr;
uint64_t mmio_ptr;
uint64_t efi_ptr;
uint64_t unused0;
uint64_t unused1;
uint64_t unused2;
uint64_t unused3;
uint64_t unused4;
} aarch64;
} arch;
/* from 128th byte, MMapEnt[], more records may follow */
MMapEnt mmap;
/* use like this:
* MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++;
* until you reach bootboot->size */
} __attribute__((packed)) bootinfo;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,31 @@
/************************
*** Team Kitty, 2020 ***
*** Sync ***
***********************/
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include <kernel/boot/boot.h>
#include <kernel/system/io.h>
#include <kernel/system/memory.h>
extern bootinfo bootldr;
extern unsigned char* environment;
extern uint8_t fb;
void DrawPixel(uint32_t x, uint32_t y, uint32_t color);
void FillScreen(uint32_t color);
void WriteString(const char* string);
void WriteChar(const char character);
void InitInterrupts();
void InitSerial();
void InitPrint();
void SetupInitialGDT();
void SetupIDT();

View File

@ -0,0 +1,68 @@
#include <stdint.h>
#include <stddef.h>
typedef struct __attribute__((packed)) {
uint16_t LowLimit;
uint16_t BaseLow;
uint8_t BaseMid;
uint8_t Access;
uint8_t Granularity;
uint8_t BaseHigh;
} GDT_ENTRY;
typedef struct __attribute__((packed)) {
uint16_t Limit;
size_t Base;
} DESC_TBL;
typedef struct __attribute__((packed)) {
uint16_t BaseLow;
uint16_t Segment;
uint8_t ISTAndZero;
uint8_t SegmentType;
uint16_t BaseMid;
uint32_t BaseHigh;
uint32_t Reserved;
} IDT_GATE;
typedef struct __attribute__((packed)) {
uint16_t BaseLow;
uint16_t SegmentSelector;
uint8_t ISTAndZero;
uint8_t Misc;
uint16_t BaseHigh;
} IDT_ENTRY;
typedef struct __attribute__((packed)) {
uint16_t SegmentLimitLow;
uint16_t BaseLow;
uint8_t BaseMid1;
uint8_t SegmentType;
uint8_t SegmentLimitHigh;
uint8_t BaseMid2;
uint32_t BaseHigh;
uint32_t Reserved;
} TSS_ENTRY;
typedef struct __attribute__((packed)) {
uint32_t Reserved0;
size_t RSP0;
size_t RSP1;
size_t RSP2;
size_t Reserved12;
size_t IST1;
size_t IST2;
size_t IST3;
size_t IST4;
size_t IST5;
size_t IST6;
size_t IST7;
size_t Reserved34;
uint16_t Reserved5;
uint16_t IOMap;
} TSS64;

View File

@ -0,0 +1,80 @@
#include <stddef.h>
typedef struct __attribute__((packed)) {
size_t ss;
size_t rsp;
size_t rflags;
size_t cs;
size_t rip;
} INTERRUPT_FRAME;
typedef struct __attribute__((packed)) {
size_t ErrorCode;
size_t rip;
size_t cs;
size_t rflags;
size_t rsp;
size_t ss;
} EXCEPTION_FRAME;
static void* IRQ_Handlers[16] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception);
void RemapIRQControllers();
void ISR0Handler(INTERRUPT_FRAME* Frame); // Divide-By-Zero
void ISR1Handler(INTERRUPT_FRAME* Frame); // Debug
void ISR2Handler(INTERRUPT_FRAME* Frame); // Non-Maskable Interrupt
void ISR3Handler(INTERRUPT_FRAME* Frame); // Breakpoint
void ISR4Handler(INTERRUPT_FRAME* Frame); // Overflow
void ISR5Handler(INTERRUPT_FRAME* Frame); // Out-of-Bounds
void ISR6Handler(INTERRUPT_FRAME* Frame); // Invalid Opcode
void ISR7Handler(INTERRUPT_FRAME* Frame); // No Coprocessor
void ISR8Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Double Fault
void ISR9Handler(INTERRUPT_FRAME* Frame); // Coprocessor Overrun
void ISR10Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Invalid TSS
void ISR11Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Segment Not Present
void ISR12Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Stack Segment Fault
void ISR13Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // General Protection Fault
void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Page Fault
void ISR15Handler(INTERRUPT_FRAME* Frame); // Unknown Interrupt
void ISR16Handler(INTERRUPT_FRAME* Frame); // Math Error / Coprocessor Fault
void ISR17Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Alignment Error
void ISR18Handler(INTERRUPT_FRAME* Frame); // Machine Check
void ISR19Handler(INTERRUPT_FRAME* Frame); // SSE Math Error
void ISR20Handler(INTERRUPT_FRAME* Frame); // Virtualization
void ISR21Handler(INTERRUPT_FRAME* Frame);
void ISR22Handler(INTERRUPT_FRAME* Frame);
void ISR23Handler(INTERRUPT_FRAME* Frame);
void ISR24Handler(INTERRUPT_FRAME* Frame);
void ISR25Handler(INTERRUPT_FRAME* Frame);
void ISR26Handler(INTERRUPT_FRAME* Frame);
void ISR27Handler(INTERRUPT_FRAME* Frame);
void ISR28Handler(INTERRUPT_FRAME* Frame);
void ISR29Handler(INTERRUPT_FRAME* Frame);
void ISR30Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode); // Security Fault
void ReservedISRHandler(INTERRUPT_FRAME* Frame);
void IRQ0Handler(INTERRUPT_FRAME* Frame);
void IRQ1Handler(INTERRUPT_FRAME* Frame);
void IRQ2Handler(INTERRUPT_FRAME* Frame);
void IRQ3Handler(INTERRUPT_FRAME* Frame);
void IRQ4Handler(INTERRUPT_FRAME* Frame);
void IRQ5Handler(INTERRUPT_FRAME* Frame);
void IRQ6Handler(INTERRUPT_FRAME* Frame);
void IRQ7Handler(INTERRUPT_FRAME* Frame);
void IRQ8Handler(INTERRUPT_FRAME* Frame);
void IRQ9Handler(INTERRUPT_FRAME* Frame);
void IRQ10Handler(INTERRUPT_FRAME* Frame);
void IRQ11Handler(INTERRUPT_FRAME* Frame);
void IRQ12Handler(INTERRUPT_FRAME* Frame);
void IRQ13Handler(INTERRUPT_FRAME* Frame);
void IRQ14Handler(INTERRUPT_FRAME* Frame);
void IRQ15Handler(INTERRUPT_FRAME* Frame);

View File

@ -0,0 +1,63 @@
#include <kernel/system/descriptors.h>
uint8_t kbdSBuffer[8];
uint8_t InputBuffer[128];
typedef struct {
uint8_t ACK;
uint8_t SelfTest;
uint8_t Echo;
uint8_t EchoCount;
uint8_t Error;
} KBD_FLAGS;
KBD_FLAGS KbdFlags;
DESC_TBL ReadGDT(void);
void WriteGDT(DESC_TBL GDTData);
DESC_TBL ReadIDT(void);
void WriteIDT(DESC_TBL IDTData);
uint16_t ReadLDT(void);
void WriteLDT(uint16_t LDTData);
uint16_t ReadTSR(void);
void WriteTSR(uint16_t TSRData);
uint32_t ReadPort(uint16_t Port, int Length);
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length);
size_t ReadModelSpecificRegister(size_t MSR);
size_t WriteModelSpecificRegister(size_t MSR, size_t Data);
uint32_t ReadVexMXCSR(void);
uint32_t WriteVexMXCSR(uint32_t Data);
uint32_t ReadMXCSR(void);
uint32_t WriteMXCSR(uint32_t Data);
size_t ReadControlRegister(int CRX);
size_t WriteControlRegister(int CRX, size_t Data);
size_t ReadExtendedControlRegister(size_t XCRX);
size_t WriteExtendedControlRegister(size_t XCRX, size_t Data);
// XCS = Extended Code Segment
size_t ReadXCS(void);
void UpdateKeyboard(uint8_t scancode);
void WaitFor8042();
void Send8042(size_t);
void WriteSerialChar(const char);
void WriteSerialString(const char*, size_t);
int SerialPrintf(const char* restrict format, ...);
void* memcpy(void* dest, void const* src, size_t len);
void* memset(void* dst, int src, size_t len);

View File

@ -0,0 +1,25 @@
#include <stddef.h>
#include <stdint.h>
#define PAGE_SIZE 4096
#define PAGES_PER_BUCKET 8
#define OFFSET_BIT(i) Memory[i / PAGES_PER_BUCKET]
#define SET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) | (1 << (i % PAGES_PER_BUCKET))
#define UNSET_BIT(i) OFFSET_BIT(i) = OFFSET_BIT(i) & (~(1 << (i % PAGES_PER_BUCKET)))
#define READ_BIT(i) ((OFFSET_BIT(i) >> (i % PAGES_PER_BUCKET)) & 0x1)
#define GET_BUCKET32(i) (*((uint32_t*) (&Memory[i / 32])))
#define PAGE_ALIGN(addr) (((addr) & 0xFFFFF000) + 0x1000)
extern size_t end;
void InitMemoryManager();
size_t AllocatePage();
void FreePage(size_t PageNumber);
size_t FirstFreePage();
void MemoryTest();

View File

@ -0,0 +1,466 @@
/************************
*** Team Kitty, 2019 ***
*** Sync ***
***********************/
// This file contains all of the bitmap fonts made by me (Curle) and taken from the public domain
// eg. http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm
const unsigned char bitfont_latin[128][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
{ 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
{ 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
{ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
{ 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
{ 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
{ 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
{ 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
{ 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
{ 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
{ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
{ 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
{ 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
{ 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
{ 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
{ 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
{ 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
{ 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
{ 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
{ 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
{ 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
{ 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
{ 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
{ 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
{ 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//)
{ 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
{ 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
{ 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
{ 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
{ 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
{ 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
{ 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
{ 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
{ 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
{ 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
{ 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
{ 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
{ 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
{ 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
{ 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
{ 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
{ 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
{ 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
{ 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
{ 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
{ 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
{ 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
{ 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
{ 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
{ 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
{ 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
{ 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
{ 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
{ 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
{ 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
{ 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
{ 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
{ 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
{ 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
{ 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
{ 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
{ 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
{ 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
{ 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
{ 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
{ 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
{ 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
{ 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
{ 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
{ 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
{ 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
{ 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
{ 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
{ 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
{ 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
{ 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
{ 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
{ 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
{ 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
{ 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
{ 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
{ 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
{ 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
};
const unsigned char bitfont_extra[96][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A0 (no break space)
{ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00}, // U+00A1 (inverted !)
{ 0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18}, // U+00A2 (dollarcents)
{ 0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00}, // U+00A3 (pound sterling)
{ 0x00, 0x00, 0x63, 0x3E, 0x36, 0x3E, 0x63, 0x00}, // U+00A4 (currency mark)
{ 0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C}, // U+00A5 (yen)
{ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+00A6 (broken pipe)
{ 0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E}, // U+00A7 (paragraph)
{ 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00A8 (diaeresis)
{ 0x3C, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3C}, // U+00A9 (copyright symbol)
{ 0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00}, // U+00AA (superscript a)
{ 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00}, // U+00AB (<<)
{ 0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00}, // U+00AC (gun pointing left)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AD (soft hyphen)
{ 0x3C, 0x42, 0x9D, 0xA5, 0x9D, 0xA5, 0x42, 0x3C}, // U+00AE (registered symbol)
{ 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00AF (macron)
{ 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B0 (degree)
{ 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00}, // U+00B1 (plusminus)
{ 0x1C, 0x30, 0x18, 0x0C, 0x3C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 2)
{ 0x1C, 0x30, 0x18, 0x30, 0x1C, 0x00, 0x00, 0x00}, // U+00B2 (superscript 3)
{ 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+00B2 (aigu)
{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+00B5 (mu)
{ 0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00}, // U+00B6 (pilcrow)
{ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, // U+00B7 (central dot)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1E}, // U+00B8 (cedille)
{ 0x08, 0x0C, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00B9 (superscript 1)
{ 0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00}, // U+00BA (superscript 0)
{ 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00}, // U+00BB (>>)
{ 0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03}, // U+00BC (1/4)
{ 0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0}, // U+00BD (1/2)
{ 0x03, 0xC4, 0x63, 0xB4, 0xDB, 0xAC, 0xE6, 0x80}, // U+00BE (3/4)
{ 0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00}, // U+00BF (inverted ?)
{ 0x07, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C0 (A grave)
{ 0x70, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00}, // U+00C1 (A aigu)
{ 0x1C, 0x36, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C2 (A circumflex)
{ 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00}, // U+00C3 (A ~)
{ 0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00}, // U+00C4 (A umlaut)
{ 0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00}, // U+00C5 (A ring)
{ 0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00}, // U+00C6 (AE)
{ 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E}, // U+00C7 (C cedille)
{ 0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C8 (E grave)
{ 0x38, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00C9 (E aigu)
{ 0x0C, 0x12, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CA (E circumflex)
{ 0x36, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00}, // U+00CB (E umlaut)
{ 0x07, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CC (I grave)
{ 0x38, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CD (I aigu)
{ 0x0C, 0x12, 0x00, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CE (I circumflex)
{ 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00CF (I umlaut)
{ 0x3F, 0x66, 0x6F, 0x6F, 0x66, 0x66, 0x3F, 0x00}, // U+00D0 (Eth)
{ 0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00}, // U+00D1 (N ~)
{ 0x0E, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D2 (O grave)
{ 0x70, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D3 (O aigu)
{ 0x3C, 0x66, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00}, // U+00D4 (O circumflex)
{ 0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x63, 0x3E, 0x00}, // U+00D5 (O ~)
{ 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00}, // U+00D6 (O umlaut)
{ 0x00, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x00, 0x00}, // U+00D7 (multiplicative x)
{ 0x5C, 0x36, 0x73, 0x7B, 0x6F, 0x36, 0x1D, 0x00}, // U+00D8 (O stroke)
{ 0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00D9 (U grave)
{ 0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DA (U aigu)
{ 0x3C, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x00}, // U+00DB (U circumflex)
{ 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+00DC (U umlaut)
{ 0x70, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00}, // U+00DD (Y aigu)
{ 0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+00DE (Thorn)
{ 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+00DF (beta)
{ 0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E0 (a grave)
{ 0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E1 (a aigu)
{ 0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00}, // U+00E2 (a circumflex)
{ 0x6E, 0x3B, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E3 (a ~)
{ 0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E4 (a umlaut)
{ 0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00}, // U+00E5 (a ring)
{ 0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00}, // U+00E6 (ae)
{ 0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+00E7 (c cedille)
{ 0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E8 (e grave)
{ 0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00E9 (e aigu)
{ 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00}, // U+00EA (e circumflex)
{ 0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00}, // U+00EB (e umlaut)
{ 0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EC (i grave)
{ 0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00ED (i augu)
{ 0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00}, // U+00EE (i circumflex)
{ 0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+00EF (i umlaut)
{ 0x1B, 0x0E, 0x1B, 0x30, 0x3E, 0x33, 0x1E, 0x00}, // U+00F0 (eth)
{ 0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00}, // U+00F1 (n ~)
{ 0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F2 (o grave)
{ 0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F3 (o aigu)
{ 0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F4 (o circumflex)
{ 0x6E, 0x3B, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F5 (o ~)
{ 0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+00F6 (o umlaut)
{ 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00}, // U+00F7 (division)
{ 0x00, 0x60, 0x3C, 0x76, 0x7E, 0x6E, 0x3C, 0x06}, // U+00F8 (o stroke)
{ 0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00F9 (u grave)
{ 0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FA (u aigu)
{ 0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FB (u circumflex)
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00}, // U+00FC (u umlaut)
{ 0x00, 0x38, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+00FD (y aigu)
{ 0x00, 0x00, 0x06, 0x3E, 0x66, 0x3E, 0x06, 0x00}, // U+00FE (thorn)
{ 0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F} // U+00FF (y umlaut)
};
const unsigned char bitfont_greek[58][8] = {
{ 0x2D, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0390 (iota with tonos and diaeresis)
{ 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0391 (Alpha)
{ 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0392 (Beta)
{ 0x3F, 0x33, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00}, // U+0393 (Gamma)
{ 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x7F, 0x00}, // U+0394 (Delta)
{ 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0395 (Epsilon)
{ 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+0396 (Zeta)
{ 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0397 (Eta)
{ 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x36, 0x1C, 0x00}, // U+0398 (Theta)
{ 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0399 (Iota)
{ 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+039A (Kappa)
{ 0x08, 0x1C, 0x1C, 0x36, 0x36, 0x63, 0x63, 0x00}, // U+039B (Lambda)
{ 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+039C (Mu)
{ 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+039D (Nu)
{ 0x7F, 0x63, 0x00, 0x3E, 0x00, 0x63, 0x7F, 0x00}, // U+039E (Xi)
{ 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+039F (Omikron)
{ 0x7F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00}, // U+03A0 (Pi)
{ 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+03A1 (Rho)
{ 0x00, 0x01, 0x02, 0x04, 0x4F, 0x90, 0xA0, 0x40}, // U+03A2
{ 0x7F, 0x63, 0x06, 0x0C, 0x06, 0x63, 0x7F, 0x00}, // U+03A3 (Sigma 2)
{ 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+03A4 (Tau)
{ 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+03A5 (Upsilon)
{ 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03A6 (Phi)
{ 0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63, 0x00}, // U+03A7 (Chi)
{ 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00}, // U+03A8 (Psi)
{ 0x3E, 0x63, 0x63, 0x63, 0x36, 0x36, 0x77, 0x00}, // U+03A9 (Omega)
{ 0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0399 (Iota with diaeresis)
{ 0x33, 0x00, 0x33, 0x33, 0x1E, 0x0C, 0x1E, 0x00}, // U+03A5 (Upsilon with diaeresis)
{ 0x70, 0x00, 0x6E, 0x3B, 0x13, 0x3B, 0x6E, 0x00}, // U+03AC (alpha aigu)
{ 0x38, 0x00, 0x1E, 0x03, 0x0E, 0x03, 0x1E, 0x00}, // U+03AD (epsilon aigu)
{ 0x38, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x30}, // U+03AE (eta aigu)
{ 0x38, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+03AF (iota aigu)
{ 0x2D, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03B0 (upsilon with tonos and diaeresis)
{ 0x00, 0x00, 0x6E, 0x3B, 0x13, 0x3B, 0x6E, 0x00}, // U+03B1 (alpha)
{ 0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03}, // U+03B2 (beta)
{ 0x00, 0x00, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x00}, // U+03B3 (gamma)
{ 0x38, 0x0C, 0x18, 0x3E, 0x33, 0x33, 0x1E, 0x00}, // U+03B4 (delta)
{ 0x00, 0x00, 0x1E, 0x03, 0x0E, 0x03, 0x1E, 0x00}, // U+03B5 (epsilon)
{ 0x00, 0x3F, 0x06, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03B6 (zeta)
{ 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x30}, // U+03B7 (eta)
{ 0x00, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x1E, 0x00}, // U+03B8 (theta)
{ 0x00, 0x00, 0x0C, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+03B9 (iota)
{ 0x00, 0x00, 0x33, 0x1B, 0x0F, 0x1B, 0x33, 0x00}, // U+03BA (kappa)
{ 0x00, 0x03, 0x06, 0x0C, 0x1C, 0x36, 0x63, 0x00}, // U+03BB (lambda)
{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03}, // U+03BC (mu)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+03BD (nu)
{ 0x1E, 0x03, 0x0E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03BE (xi)
{ 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03BF (omikron)
{ 0x00, 0x00, 0x7F, 0x36, 0x36, 0x36, 0x36, 0x00}, // U+03C0 (pi)
{ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x36, 0x06, 0x06}, // U+03C1 (rho)
{ 0x00, 0x00, 0x3E, 0x03, 0x03, 0x1E, 0x30, 0x1C}, // U+03C2 (sigma 1)
{ 0x00, 0x00, 0x7E, 0x1B, 0x1B, 0x1B, 0x0E, 0x00}, // U+03C3 (sigma 2)
{ 0x00, 0x00, 0x7E, 0x18, 0x18, 0x58, 0x30, 0x00}, // U+03C4 (tau)
{ 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+03C5 (upsilon)
{ 0x00, 0x00, 0x76, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03C6 (phi)
{ 0x00, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+03C7 (chi)
{ 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x00}, // U+03C8 (psi)
{ 0x00, 0x00, 0x36, 0x63, 0x6B, 0x7F, 0x36, 0x00} // U+03C9 (omega)
};
const unsigned char bitfont_box[128][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00}, // U+2500 (thin horizontal)
{ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // U+2501 (thick horizontal)
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}, // U+2502 (thin vertical)
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // U+2503 (thich vertical)
{ 0x00, 0x00, 0x00, 0x00, 0xBB, 0x00, 0x00, 0x00}, // U+2504 (thin horizontal dashed)
{ 0x00, 0x00, 0x00, 0xBB, 0xBB, 0x00, 0x00, 0x00}, // U+2505 (thick horizontal dashed)
{ 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08}, // U+2506 (thin vertical dashed)
{ 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18}, // U+2507 (thich vertical dashed)
{ 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00}, // U+2508 (thin horizontal dotted)
{ 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00}, // U+2509 (thick horizontal dotted)
{ 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08}, // U+250A (thin vertical dotted)
{ 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18}, // U+250B (thich vertical dotted)
{ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x08, 0x08}, // U+250C (down L, right L)
{ 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+250D (down L, right H)
{ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18}, // U+250E (down H, right L)
{ 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+250F (down H, right H)
{ 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08}, // U+2510 (down L, left L)
{ 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x08, 0x08, 0x08}, // U+2511 (down L, left H)
{ 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18}, // U+2512 (down H, left L)
{ 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+2513 (down H, left H)
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x00, 0x00, 0x00}, // U+2514 (up L, right L)
{ 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x00, 0x00, 0x00}, // U+2515 (up L, right H)
{ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00}, // U+2516 (up H, right L)
{ 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x00, 0x00, 0x00}, // U+2517 (up H, right H)
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x00, 0x00, 0x00}, // U+2518 (up L, left L)
{ 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x00, 0x00, 0x00}, // U+2519 (up L, left H)
{ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00}, // U+251A (up H, left L)
{ 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x00, 0x00, 0x00}, // U+251B (up H, left H)
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x08, 0x08, 0x08}, // U+251C (down L, right L, up L)
{ 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+251D (down L, right H, up L)
{ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x08, 0x08, 0x08}, // U+251E (down L, right L, up H)
{ 0x08, 0x08, 0x08, 0x08, 0xf8, 0x18, 0x18, 0x18}, // U+251F (down H, right L, up L)
{ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18}, // U+2520 (down H, right L, up H)
{ 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x08, 0x08, 0x08}, // U+2521 (down L, right H, up H)
{ 0x08, 0x08, 0x08, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+2522 (down H, right H, up L)
{ 0x18, 0x18, 0x18, 0xf8, 0xf8, 0x18, 0x18, 0x18}, // U+2523 (down H, right H, up H)
{ 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08}, // U+2524 (down L, left L, up L)
{ 0x08, 0x08, 0x08, 0x0f, 0x0f, 0x08, 0x08, 0x08}, // U+2525 (down L, left H, up L)
{ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x08, 0x08, 0x08}, // U+2526 (down L, left L, up H)
{ 0x08, 0x08, 0x08, 0x08, 0x1f, 0x18, 0x18, 0x18}, // U+2527 (down H, left L, up L)
{ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18}, // U+2528 (down H, left L, up H)
{ 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x08, 0x08, 0x08}, // U+2529 (down L, left H, up H)
{ 0x08, 0x08, 0x08, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+252A (down H, left H, up L)
{ 0x18, 0x18, 0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18}, // U+252B (down H, left H, up H)
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08}, // U+252C (down L, right L, left L)
{ 0x00, 0x00, 0x00, 0x0f, 0xff, 0x08, 0x08, 0x08}, // U+252D (down L, right L, left H)
{ 0x00, 0x00, 0x00, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+252E (down L, right H, left L)
{ 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+252F (down L, right H, left H)
{ 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18}, // U+2530 (down H, right L, left L)
{ 0x00, 0x00, 0x00, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2531 (down H, right L, left H)
{ 0x00, 0x00, 0x00, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+2532 (down H, right H, left L)
{ 0x00, 0x00, 0x00, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+2533 (down H, right H, left H)
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x00, 0x00, 0x00}, // U+2534 (up L, right L, left L)
{ 0x08, 0x08, 0x08, 0x0f, 0xff, 0x00, 0x00, 0x00}, // U+2535 (up L, right L, left H)
{ 0x08, 0x08, 0x08, 0xf8, 0xff, 0x00, 0x00, 0x00}, // U+2536 (up L, right H, left L)
{ 0x08, 0x08, 0x08, 0xff, 0xff, 0x00, 0x00, 0x00}, // U+2537 (up L, right H, left H)
{ 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00}, // U+2538 (up H, right L, left L)
{ 0x18, 0x18, 0x18, 0x1f, 0xff, 0x00, 0x00, 0x00}, // U+2539 (up H, right L, left H)
{ 0x18, 0x18, 0x18, 0xf8, 0xff, 0x00, 0x00, 0x00}, // U+253A (up H, right H, left L)
{ 0x18, 0x18, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00}, // U+253B (up H, right H, left H)
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08}, // U+253C (up L, right L, left L, down L)
{ 0x08, 0x08, 0x08, 0x0f, 0xff, 0x08, 0x08, 0x08}, // U+253D (up L, right L, left H, down L)
{ 0x08, 0x08, 0x08, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+253E (up L, right H, left L, down L)
{ 0x08, 0x08, 0x08, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+253F (up L, right H, left H, down L)
{ 0x18, 0x18, 0x18, 0x18, 0xff, 0x08, 0x08, 0x08}, // U+2540 (up H, right L, left L, down L)
{ 0x08, 0x08, 0x08, 0x08, 0xff, 0x18, 0x18, 0x18}, // U+2541 (up L, right L, left L, down H)
{ 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18}, // U+2542 (up H, right L, left L, down H)
{ 0x18, 0x18, 0x18, 0x1f, 0xff, 0x08, 0x08, 0x08}, // U+2543 (up H, right L, left H, down L)
{ 0x18, 0x18, 0x18, 0xf8, 0xff, 0x08, 0x08, 0x08}, // U+2544 (up H, right H, left L, down L)
{ 0x08, 0x08, 0x08, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2545 (up L, right L, left H, down H)
{ 0x08, 0x08, 0x08, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+2546 (up L, right H, left L, down H)
{ 0x08, 0x08, 0x08, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+2547 (up L, right H, left H, down H)
{ 0x18, 0x18, 0x18, 0xff, 0xff, 0x08, 0x08, 0x08}, // U+254B (up H, right H, left H, down L)
{ 0x18, 0x18, 0x18, 0xf8, 0xff, 0x18, 0x18, 0x18}, // U+254A (up H, right H, left L, down H)
{ 0x18, 0x18, 0x18, 0x1f, 0xff, 0x18, 0x18, 0x18}, // U+2549 (up H, right L, left H, down H)
{ 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18}, // U+254B (up H, right H, left H, down H)
{ 0x00, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00}, // U+254C (thin horizontal broken)
{ 0x00, 0x00, 0x00, 0xE7, 0xE7, 0x00, 0x00, 0x00}, // U+254D (thick horizontal broken)
{ 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08}, // U+254E (thin vertical broken)
{ 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18}, // U+254F (thich vertical broken)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2550 (double horizontal)
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // U+2551 (double vertical)
{ 0x00, 0x00, 0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+2552 (down L, right D)
{ 0x00, 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14}, // U+2553 (down D, right L)
{ 0x00, 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14}, // U+2554 (down D, right D)
{ 0x00, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2555 (down L, left D)
{ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14}, // U+2556 (down D, left L)
{ 0x00, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14}, // U+2557 (down D, left D)
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00}, // U+2558 (up L, right D)
{ 0x14, 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00}, // U+2559 (up D, right L)
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00}, // U+255A (up D, right D)
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00}, // U+255B (up L, left D)
{ 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00}, // U+255C (up D, left L)
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00}, // U+255D (up D, left D)
{ 0x08, 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x08, 0x08}, // U+255E (up L, down L, right D)
{ 0x14, 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14}, // U+255F (up D, down D, right L)
{ 0x14, 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14}, // U+2560 (up D, down D, right D)
{ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08}, // U+2561 (up L, down L, left D)
{ 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14}, // U+2562 (up D, down D, left L)
{ 0x14, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14}, // U+2563 (up D, down D, left D)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08}, // U+2564 (left D, right D, down L)
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14}, // U+2565 (left L, right L, down D)
{ 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14}, // U+2566 (left D, right D, down D)
{ 0x08, 0x08, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00}, // U+2567 (left D, right D, up L)
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00}, // U+2568 (left L, right L, up D)
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00}, // U+2569 (left D, right D, up D)
{ 0x08, 0x08, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08}, // U+256A (left D, right D, down L, up L)
{ 0x14, 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14}, // U+256B (left L, right L, down D, up D)
{ 0x14, 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14}, // U+256C (left D, right D, down D, up D)
{ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x08, 0x08}, // U+256D (curve down-right)
{ 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x08}, // U+256E (curve down-left)
{ 0x08, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00}, // U+256F (curve up-left)
{ 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00}, // U+2570 (curve up-right)
{ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, // U+2571 (diagonal bottom-left to top-right)
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, // U+2572 (diagonal bottom-right to top-left)
{ 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}, // U+2573 (diagonal cross)
{ 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00}, // U+2574 (left L)
{ 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}, // U+2575 (up L)
{ 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00}, // U+2576 (right L)
{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08}, // U+2577 (down L)
{ 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00}, // U+2578 (left H)
{ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00}, // U+2579 (up H)
{ 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x00}, // U+257A (right H)
{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18}, // U+257B (down H)
{ 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00}, // U+257C (right H, left L)
{ 0x08, 0x08, 0x08, 0x08, 0x18, 0x18, 0x18, 0x18}, // U+257D (up L, down H)
{ 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00}, // U+257E (right L, left H)
{ 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0x08} // U+257F (up H, down L)
};
const unsigned char bitfont_block[32][8] = {
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, // U+2580 (top half)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+2581 (box 1/8)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}, // U+2582 (box 2/8)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF}, // U+2583 (box 3/8)
{ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2584 (bottom half)
{ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2585 (box 5/8)
{ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2586 (box 6/8)
{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2587 (box 7/8)
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2588 (solid)
{ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // U+2589 (box 7/8)
{ 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F}, // U+258A (box 6/8)
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, // U+258B (box 5/8)
{ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // U+258C (left half)
{ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}, // U+258D (box 3/8)
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}, // U+258E (box 2/8)
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, // U+258F (box 1/8)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2590 (right half)
{ 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00}, // U+2591 (25% solid)
{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}, // U+2592 (50% solid)
{ 0xFF, 0xAA, 0xFF, 0x55, 0xFF, 0xAA, 0xFF, 0x55}, // U+2593 (75% solid)
{ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+2594 (box 1/8)
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, // U+2595 (box 1/8)
{ 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F}, // U+2596 (box bottom left)
{ 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0}, // U+2597 (box bottom right)
{ 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00}, // U+2598 (box top left)
{ 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF}, // U+2599 (boxes left and bottom)
{ 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0}, // U+259A (boxes top-left and bottom right)
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259B (boxes top and left)
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0}, // U+259C (boxes top and right)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00}, // U+259D (box top right)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F}, // U+259E (boxes top right and bottom left)
{ 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF}, // U+259F (boxes right and bottom)
};

20
chroma/kernel.c Normal file
View File

@ -0,0 +1,20 @@
#include <kernel/chroma.h>
void _start(void) {
SerialPrintf("\r\nBooting Chroma..\r\n");
InitPrint();
SetupInitialGDT();
SetupIDT();
InitInterrupts();
InitMemoryManager();
MemoryTest();
InitPaging();
for(;;) { }
}

202
chroma/system/cpu.c Normal file
View File

@ -0,0 +1,202 @@
#include <kernel/chroma.h>
#include <kernel/system/interrupts.h>
#define NMI_STACK 4096
#define DF_STACK 4096
#define MC_STACK 4096
#define BP_STACK 4096
__attribute__((aligned(64))) static volatile unsigned char NMIStack[NMI_STACK] = {0};
__attribute__((aligned(64))) static volatile unsigned char DFStack[DF_STACK] = {0};
__attribute__((aligned(64))) static volatile unsigned char MCStack[MC_STACK] = {0};
__attribute__((aligned(64))) static volatile unsigned char BPStack[BP_STACK] = {0};
__attribute__((aligned(64))) static volatile size_t InitGDT[5] = {
0,
0x00af9a000000ffff,
0x00cf92000000ffff,
0x0080890000000067,
0
};
__attribute__((aligned(64))) static volatile TSS64 TSSEntries = {0};
__attribute__((aligned(64))) static volatile IDT_GATE IDTEntries[256] = {0};
static void RefreshCS() {
__asm__ __volatile__ ("mov $16, %ax \n\t" // 16 = 0x10 = index 2 of GDT
"mov %ax, %ds \n\t" // Next few lines prepare the processor for the sudden change into the data segment
"mov %ax, %es \n\t" //
"mov %ax, %fs \n\t" //
"mov %ax, %gs \n\t" //
"mov %ax, %ss \n\t" //
"movq $8, %rdx \n\t" // 8 = 0x8 = index 1 of GDT
"leaq 4(%rip), %rax \n\t" // Returns execution to immediately after the iret, required for changing %cs while in long mode. - this is currently literally the only way to do it.
"pushq %rdx \n\t" //
"pushq %rax \n\t" //
"lretq \n\t"); //
}
void SetupInitialGDT() {
DESC_TBL GDTData = {0};
size_t TSSBase = (uint64_t) (&TSSEntries);
uint16_t TSSLower = (uint16_t) TSSBase;
uint8_t TSSMid1 = (uint8_t) (TSSBase >> 16);
uint8_t TSSMid2 = (uint8_t) (TSSBase >> 24);
uint32_t TSSHigher = (uint32_t) (TSSBase >> 32);
GDTData.Limit = sizeof(InitGDT) - 1;
GDTData.Base = (size_t) InitGDT;
( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseLow = TSSLower;
( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseMid1 = TSSMid1;
( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseMid2 = TSSMid2;
( (TSS_ENTRY*) (&((GDT_ENTRY*) InitGDT)[3]) )->BaseHigh = TSSHigher;
WriteGDT(GDTData);
WriteTSR(3 << 3);
RefreshCS();
}
static void SetISR(size_t ISRNum, size_t ISRAddr) {
uint16_t ISRBaseLow = (uint16_t) ISRAddr;
uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16);
uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32);
IDTEntries[ISRNum].BaseLow = ISRBaseLow;
IDTEntries[ISRNum].Segment = 0x08;
IDTEntries[ISRNum].ISTAndZero = 0;
IDTEntries[ISRNum].SegmentType = 0x8E;
IDTEntries[ISRNum].BaseMid = ISRBaseMid;
IDTEntries[ISRNum].BaseHigh = ISRBaseHigh;
IDTEntries[ISRNum].Reserved = 0;
}
static void SetISRNMI(size_t ISRNum, size_t ISRAddr) {
uint16_t ISRBaseLow = (uint16_t) ISRAddr;
uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16);
uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32);
IDTEntries[ISRNum].BaseLow = ISRBaseLow;
IDTEntries[ISRNum].Segment = 0x08;
IDTEntries[ISRNum].ISTAndZero = 1;
IDTEntries[ISRNum].SegmentType = 0x8E;
IDTEntries[ISRNum].BaseMid = ISRBaseMid;
IDTEntries[ISRNum].BaseHigh = ISRBaseHigh;
IDTEntries[ISRNum].Reserved = 0;
}
static void SetISRDF(size_t ISRNum, size_t ISRAddr) {
uint16_t ISRBaseLow = (uint16_t) ISRAddr;
uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16);
uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32);
IDTEntries[ISRNum].BaseLow = ISRBaseLow;
IDTEntries[ISRNum].Segment = 0x08;
IDTEntries[ISRNum].ISTAndZero = 2;
IDTEntries[ISRNum].SegmentType = 0x8E;
IDTEntries[ISRNum].BaseMid = ISRBaseMid;
IDTEntries[ISRNum].BaseHigh = ISRBaseHigh;
IDTEntries[ISRNum].Reserved = 0;
}
static void SetISRMC(size_t ISRNum, size_t ISRAddr) {
uint16_t ISRBaseLow = (uint16_t) ISRAddr;
uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16);
uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32);
IDTEntries[ISRNum].BaseLow = ISRBaseLow;
IDTEntries[ISRNum].Segment = 0x08;
IDTEntries[ISRNum].ISTAndZero = 3;
IDTEntries[ISRNum].SegmentType = 0x8E;
IDTEntries[ISRNum].BaseMid = ISRBaseMid;
IDTEntries[ISRNum].BaseHigh = ISRBaseHigh;
IDTEntries[ISRNum].Reserved = 0;
}
static void SetISRBP(size_t ISRNum, size_t ISRAddr) {
uint16_t ISRBaseLow = (uint16_t) ISRAddr;
uint16_t ISRBaseMid = (uint16_t) (ISRAddr >> 16);
uint32_t ISRBaseHigh = (uint32_t) (ISRAddr >> 32);
IDTEntries[ISRNum].BaseLow = ISRBaseLow;
IDTEntries[ISRNum].Segment = 0x08;
IDTEntries[ISRNum].ISTAndZero = 4;
IDTEntries[ISRNum].SegmentType = 0x8E;
IDTEntries[ISRNum].BaseMid = ISRBaseMid;
IDTEntries[ISRNum].BaseHigh = ISRBaseHigh;
IDTEntries[ISRNum].Reserved = 0;
}
void SetupIDT() {
DESC_TBL IDTData = {0};
IDTData.Limit = (sizeof(IDT_GATE) * 256) - 1;
IDTData.Base = (size_t) &IDTEntries;
//memset(&IDTEntries, 0, sizeof(IDT_GATE) * 256);
RemapIRQControllers();
*(size_t*) (&TSSEntries.IST1) = (size_t) (NMIStack + NMI_STACK);
*(size_t*) (&TSSEntries.IST2) = (size_t) (DFStack + DF_STACK);
*(size_t*) (&TSSEntries.IST3) = (size_t) (MCStack + MC_STACK);
*(size_t*) (&TSSEntries.IST4) = (size_t) (BPStack + BP_STACK);
SetISR (0, (size_t) ISR0Handler);
SetISRBP (1, (size_t) ISR1Handler);
SetISRNMI (2, (size_t) ISR2Handler);
SetISRBP (3, (size_t) ISR3Handler);
SetISR (4, (size_t) ISR4Handler);
SetISR (5, (size_t) ISR5Handler);
SetISR (6, (size_t) ISR6Handler);
SetISR (7, (size_t) ISR7Handler);
SetISRDF (8, (size_t) ISR8Handler);
SetISR (9, (size_t) ISR9Handler);
SetISR (10, (size_t) ISR10Handler);
SetISR (11, (size_t) ISR11Handler);
SetISR (12, (size_t) ISR12Handler);
SetISR (13, (size_t) ISR13Handler);
SetISR (14, (size_t) ISR14Handler);
SetISR (15, (size_t) ISR15Handler);
SetISR (16, (size_t) ISR16Handler);
SetISR (17, (size_t) ISR17Handler);
SetISRMC (18, (size_t) ISR18Handler);
SetISR (19, (size_t) ISR19Handler);
SetISR (20, (size_t) ISR20Handler);
SetISR (30, (size_t) ISR30Handler);
for(size_t i = 1; i < 11; i++) {
if(i != 9) {
SetISR(i + 20, (size_t) ReservedISRHandler);
}
}
SetISR(32, (size_t) IRQ0Handler);
SetISR(33, (size_t) IRQ1Handler);
SetISR(34, (size_t) IRQ2Handler);
SetISR(35, (size_t) IRQ3Handler);
SetISR(36, (size_t) IRQ4Handler);
SetISR(37, (size_t) IRQ5Handler);
SetISR(38, (size_t) IRQ6Handler);
SetISR(39, (size_t) IRQ7Handler);
SetISR(40, (size_t) IRQ8Handler);
SetISR(41, (size_t) IRQ9Handler);
SetISR(42, (size_t) IRQ10Handler);
SetISR(43, (size_t) IRQ11Handler);
SetISR(44, (size_t) IRQ12Handler);
SetISR(45, (size_t) IRQ13Handler);
SetISR(46, (size_t) IRQ14Handler);
SetISR(47, (size_t) IRQ15Handler);
//TODO: ISRs 32 to 256
WriteIDT(IDTData);
}

View File

@ -0,0 +1,115 @@
#include <kernel/chroma.h>
char keys[128] = {
0, 27,
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
0,
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '#',
0,
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
0,
'*', 0,
' ', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0,
0,
0,
0,
0,
0,
'-',
0,
0,
0,
'+',
0,
0,
0,
0,
0,
0, 0, 0,
0,
0,
0,
};
void UpdateKeyboard(uint8_t msg) {
InputBuffer[0] = msg;
switch(msg) {
case 0x0:
KbdFlags.Error = 1;
//ResendBuffer();
break;
case 0xAA:
KbdFlags.SelfTest = 1;
break;
case 0xEE:
KbdFlags.Echo = 0;
KbdFlags.EchoCount = 2;
KbdEcho();
break;
case 0xFA:
KbdFlags.ACK = 1;
//ProgressBuffer();
break;
case 0xFC:
case 0xFD:
KbdFlags.SelfTest = 0;
KbdFlags.Error = 1;
//RestartKbd();
break;
case 0xFE:
//ResendBuffer();
break;
case 0xFF:
KbdFlags.Error = 1;
//ResendBuffer();
break;
default:
break;
}
if(msg & 0x80) {
} else {
SerialPrintf("Key pressed %c\r\n", keys[msg]);
WriteChar(keys[msg]);
}
}
void KbdEcho() {
if(!KbdFlags.EchoCount) {
if(!KbdFlags.Echo) {
Send8042(0xEE);
}
} else {
KbdFlags.EchoCount = 0;
KbdFlags.Echo = 0;
}
}
void Send8042(size_t info) {
for(size_t i = 0; i < 8; i++) {
unsigned char chr = (unsigned char) info;
if(chr != 0) {
WritePort(0x60, chr, 1);
WaitFor8042();
}
}
}
void WaitFor8042() {
bool full = true;
while(full) {
full = ReadPort(0x64, 1) & 1;
}
}

378
chroma/system/interrupts.c Normal file
View File

@ -0,0 +1,378 @@
/************************
*** Team Kitty, 2019 ***
*** Sync ***
***********************/
/* This file contains all of the ISR and IRQ
* (Interrupt Service Request) functions.
*
* As they use the GCC interrupt attribute,
* this file must be compiled without red-
* zone protection, thus all of these
* functions are in their own file to
* accomodate this.
*
* Additionally, the kernel now has SSE/AVX support.
* So this file and this file *alone* must be compiled with
* -mgeneral-regs-only
*
* Calling a function like so:
*
* __attribute__((interrupt)) isr1(registers_t* frame) {}
*
* allows the function to be used to serve
* interrupts - GCC compiles it under unique
* conditions, as it preserves the state of
* the processor and stack between execution,
* as well as using the IRET instruction to
* return to the middle of the previous function.
*
* There is also a version of the interrupt
* attribute which allows for error handlers,
* these having a size_t input as an error code.
*/
#include <kernel/chroma.h>
#include <kernel/system/interrupts.h>
#include <stdbool.h>
typedef unsigned long long int uword_t;
/* All of the ISR routines call this function for now.
! This function is NOT leaf, and it might clobber the stack.
! Be careful!
*/
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Exception) {
/* Only the first 32 ISR/IRQs are reserved for exceptions by the CPU. We can handle up to 512 interrupts total, though. */
if(Exception < 32) {
FillScreen(0x0000FF00);
/* ExceptionStrings is an array of c-strings defined in kernel.h */
//serialPrint(ExceptionStrings[Exception]);
//serialPrint(" Exception.\r\n");
//printf("%s exception!", ExceptionStrings[Exception]);
//panic();
}
}
/* The common handler for exceptions that throw error codes, which give us useful insight
into what went wrong. In pure Curle style, though, we just ignore the error code. */
void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception) {
if(Exception < 32) {
FillScreen(0x00FF0000);
SerialPrintf("ISR Error %d raised, EC %d!\r\n", Exception, ErrorCode);
while(true) {}
//serialPrint(ExceptionStrings[Exception]);
//serialPrintf(" Exception. Context given: %d\r\n", Frame->ErrorCode);
//printf("%s exception. Context: %x", ExceptionStrings[Exception], Frame->ErrorCode);
//panic();
}
}
/* Likewise, this function is common to all IRQ handlers. It calls the assigned routine,
which was set up earlier by irq_install.*/
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interrupt) {
// First we need to define a function pointer..
void (*Handler)(INTERRUPT_FRAME* Frame);
// Tell the user we've got an interrupt in..
//serial_print(0x3F8, "[INFO] Received IRQ: " + interrupt);
//printf("[INFO] Received IRQ: %x", Interrupt);
/* We set all uninitialized routines to 0, so the if(handler) check here allows us to
safely tell whether we've actually got something for this IRQ. */
Handler = IRQ_Handlers[Interrupt];
// If there's something there,
if(Handler) {
SerialPrintf("IRQ %d raised!\r\n", Interrupt);
// Call the handler.
Handler(Frame);
}
/* The Slave PIC must be told it's been read in order to receive another 8+ IRQ. */
if(Interrupt > 7)
WritePort(0xA0, 0x20, 1);
/* In either case, we tell the Master PIC it's been read to receive any IRQ. */
WritePort(0x20, 0x20, 1);
}
/* However, in order to actually be able to receive IRQs, we need to remap the PICs. */
void RemapIRQControllers() {
/* 0x20 is the Master PIC,
0xA0 is the Slave PIC. */
WritePort(0x20, 0x11, 1);
WritePort(0xA0, 0x11, 1);
WritePort(0x21, 0x20, 1);
WritePort(0xA1, 0x28, 1);
WritePort(0x21, 0x04, 1);
WritePort(0xA1, 0x02, 1);
WritePort(0x21, 0x01, 1);
WritePort(0xA1, 0x01, 1);
WritePort(0x21, 0x0, 1);
WritePort(0xA1, 0x0, 1);
}
/* In order to actually handle the IRQs, though, we need to tell the kernel *where* the handlers are. */
/* A simple wrapper that adds a function pointer to the IRQ array. */
void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame)) {
IRQ_Handlers[IRQ] = Handler;
}
/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */
void UninstallIRQHandler(int IRQ) {
IRQ_Handlers[IRQ] = 0; // 0 is used in the common check to make sure that the function is callable.
// This removes this irq from that check, ergo the function will no longer be called.
}
void EmptyIRQ(INTERRUPT_FRAME* frame) {
// Flash the borders green, then back to blue
for(size_t y = 0; y < bootldr.fb_height; y++) {
for(size_t x = 0; x < 20; x++) {
DrawPixel(x, y, 0x0000FF00);
}
for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) {
DrawPixel(x, y, 0x0000FF00);
}
}
for(size_t x = 0; x < bootldr.fb_width; x++) {
for(size_t y = 0; y < 20; y++) {
DrawPixel(x, y, 0x0000FF00);
}
for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) {
DrawPixel(x, y, 0x0000FF00);
}
}
for(size_t y = 0; y < bootldr.fb_height; y++) {
for(size_t x = 0; x < 20; x++) {
DrawPixel(x, y, 0x000000FF);
}
for(size_t x = (bootldr.fb_width - 20); x < bootldr.fb_width; x++) {
DrawPixel(x, y, 0x000000FF);
}
}
for(size_t x = 0; x < bootldr.fb_width; x++) {
for(size_t y = 0; y < 20; y++) {
DrawPixel(x, y, 0x000000FF);
}
for(size_t y = (bootldr.fb_height - 20); y < bootldr.fb_height; y++) {
DrawPixel(x, y, 0x000000FF);
}
}
}
static void KeyboardCallback(INTERRUPT_FRAME* frame) {
uint8_t msg = ReadPort(0x60, 1);
UpdateKeyboard(msg);
WaitFor8042();
}
void InitInterrupts() {
size_t RFLAGS = ReadControlRegister('f');
if(!(RFLAGS & (1 << 9))) {
WriteControlRegister('f', RFLAGS | (1 << 9));
}
InstallIRQ(1, &KeyboardCallback);
Send8042(0xF002);
__asm__ __volatile__("sti");
}
/* The interrupt numbers, their meanings, and
* special information is laid out below:
*
* 0 - Divide by Zero
* 1 - Debug
* 2 - Non-Maskable
* 3 - Breakpoint
* 4 - Into Detected Overflow
* 5 - Out of Bounds
* 6 - Invalid Opcode
* 7 - No Coprocessor
* 8 - Double Fault * (With Error)
* 9 - Coprocessor Segment Overrun
* 10 - Bad TSS * (With Error)
* 11 - Segment Not Present * (With Error)
* 12 - Stack Fault * (With Error)
* 13 - General Protection Fault * (With Error)
* 14 - Page Fault * (With Error)
* 15 - Unknown Interrupt
* 16 - Coprocessor Fault
* 17 - Alignment Check
* 18 - Machine Check
* 19 to 31 - Reserved
*/
__attribute__((interrupt)) void ISR0Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 0);
}
__attribute__((interrupt)) void ISR1Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 1);
}
__attribute__((interrupt)) void ISR2Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 2);
}
__attribute__((interrupt)) void ISR3Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 3);
}
__attribute__((interrupt)) void ISR4Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 4);
}
__attribute__((interrupt)) void ISR5Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 5);
}
__attribute__((interrupt)) void ISR6Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 6);
}
__attribute__((interrupt)) void ISR7Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 7);
}
__attribute__((interrupt)) void ISR8Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 8);
}
__attribute__((interrupt)) void ISR9Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 9);
}
__attribute__((interrupt)) void ISR10Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 10);
}
__attribute__((interrupt)) void ISR11Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 11);
}
__attribute__((interrupt)) void ISR12Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 12);
}
__attribute__((interrupt)) void ISR13Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 13); // General Protection
}
__attribute__((interrupt)) void ISR14Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 14);
}
__attribute__((interrupt)) void ISR15Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 15);
}
__attribute__((interrupt)) void ISR16Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 16);
}
__attribute__((interrupt)) void ISR17Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 17);
}
__attribute__((interrupt)) void ISR18Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 18);
}
__attribute__((interrupt)) void ISR19Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 19);
}
__attribute__((interrupt)) void ISR20Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 20);
}
__attribute__((interrupt)) void ISR21Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 21);
}
__attribute__((interrupt)) void ISR22Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 22);
}
__attribute__((interrupt)) void ISR23Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 23);
}
__attribute__((interrupt)) void ISR24Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 24);
}
__attribute__((interrupt)) void ISR25Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 25);
}
__attribute__((interrupt)) void ISR26Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 26);
}
__attribute__((interrupt)) void ISR27Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 27);
}
__attribute__((interrupt)) void ISR28Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 28);
}
__attribute__((interrupt)) void ISR29Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 29);
}
__attribute__((interrupt)) void ISR30Handler(INTERRUPT_FRAME* Frame, size_t ErrorCode) {
ISR_Error_Common(Frame, ErrorCode, 30);
}
__attribute__((interrupt)) void ISR31Handler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 31);
}
__attribute__((interrupt)) void ReservedISRHandler(INTERRUPT_FRAME* Frame) {
ISR_Common(Frame, 33); // if < 32, isn't handled.
// Effectively disables this ISR.
}
__attribute__((interrupt)) void IRQ0Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 0);
}
__attribute__((interrupt)) void IRQ1Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 1); // Keyboard handler
}
__attribute__((interrupt)) void IRQ2Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 2);
}
__attribute__((interrupt)) void IRQ3Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 3);
}
__attribute__((interrupt)) void IRQ4Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 4);
}
__attribute__((interrupt)) void IRQ5Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 5);
}
__attribute__((interrupt)) void IRQ6Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 6);
}
__attribute__((interrupt)) void IRQ7Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 7);
}
__attribute__((interrupt)) void IRQ8Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 8);
}
__attribute__((interrupt)) void IRQ9Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 9);
}
__attribute__((interrupt)) void IRQ10Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 10);
}
__attribute__((interrupt)) void IRQ11Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 11);
}
__attribute__((interrupt)) void IRQ12Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 12);
}
__attribute__((interrupt)) void IRQ13Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 13);
}
__attribute__((interrupt)) void IRQ14Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 14);
}
__attribute__((interrupt)) void IRQ15Handler(INTERRUPT_FRAME* Frame) {
IRQ_Common(Frame, 15);
}

124
chroma/system/mem.c Normal file
View File

@ -0,0 +1,124 @@
#include <kernel/chroma.h>
uint8_t* Memory = ((uint8_t*)(&end));
uint8_t MemoryStart;
uint32_t MemoryPages;
uint32_t MemoryLength;
void InitMemoryManager() {
size_t BootstructSize = bootldr.size;
size_t BootstructLoc = (size_t) &bootldr;
size_t BootstructEnd = BootstructLoc + BootstructSize;
size_t MemorySize = 0, MemMapEntryCount = 0;
MMapEnt* MemMap = &bootldr.mmap;
while((size_t) MemMap < BootstructEnd) {
if(MMapEnt_IsFree(MemMap)) {
MemorySize += MMapEnt_Size(MemMap);
}
MemMapEntryCount++;
MemMap++;
}
MemoryPages = MemorySize / PAGE_SIZE;
MemoryLength = MemoryPages / PAGES_PER_BUCKET;
if(MemoryLength * PAGES_PER_BUCKET < MemoryPages)
MemoryLength++; // Always round up
memset(Memory, 0, MemoryLength);
MemoryStart = (uint8_t*)PAGE_ALIGN(((uint32_t)(Memory + MemoryLength)));
SerialPrintf("Initializing Memory.\r\n");
SerialPrintf("%u MB of memory detected.\r\n", (MemorySize / 1024) / 1024);
for(size_t i = 0; i < MemoryLength; i++) {
if(Memory[i] != 0)
SerialPrintf("Memory at 0x%p is not empty!", Memory + i);
}
}
size_t AllocatePage() {
size_t FreePage = FirstFreePage();
SET_BIT(FreePage);
return FreePage;
}
void FreePage(size_t Page) {
UNSET_BIT(Page);
}
size_t FirstFreePage() {
for(size_t i = 0; i < MemoryPages; i++) {
if(!READ_BIT(i))
return i;
}
SerialPrintf("Memory manager: Critical!\r\n");
return (size_t) -1;
}
void MemoryTest() {
SerialPrintf("Initializing basic memory test..\r\n");
bool Passed = true;
size_t FirstPage = FirstFreePage();
void* FirstPageAlloc = AllocatePage();
size_t SecondPage = FirstFreePage();
void* SecondPageAlloc = AllocatePage();
if(!(FirstPage == 0 && SecondPage == 1)) {
Passed = false;
SerialPrintf("First iteration: Failed, First page %x, Second page %x.\r\n", FirstPage, SecondPage);
}
FreePage(SecondPage);
SecondPage = FirstFreePage();
if(SecondPage != 1)
Passed = false;
FreePage(FirstPage);
FirstPage = FirstFreePage();
if(FirstPage != 0)
Passed = false;
if(Passed)
SerialPrintf("Memory test passed.\r\n");
else {
SerialPrintf("Memory test failed.\r\n");
SerialPrintf("First page %x, Second page %x.\r\n", FirstPage, SecondPage);
}
}
void* memcpy(void* dest, void const* src, size_t len) {
unsigned char* dst = (unsigned char*) dest;
const unsigned char* source = (const unsigned char*) src;
for(size_t i = 0; i < len; i++) {
dst[i] = source[i];
}
return dest;
}
void* memset(void* dst, int src, size_t len) {
unsigned char* buf = (unsigned char*) dst;
for(size_t i = 0; i < len; i++) {
buf[i] = (unsigned char) src;
}
return dst;
}

216
chroma/system/rw.c Normal file
View File

@ -0,0 +1,216 @@
#include <kernel/chroma.h>
uint32_t ReadPort(uint16_t Port, int Length) {
uint32_t Data = 0;
uint16_t Data16 = 0;
uint8_t Data8 = 0;
if(Length == 1) {
__asm__ __volatile__ ("inb %[address], %[value]" : [value] "=a" (Data8) : [address] "d" (Port) :);
Data = (uint32_t) Data8;
} else if(Length == 2) {
__asm__ __volatile__ ("inw %[address], %[value]" : [value] "=a" (Data16) : [address] "d" (Port) :);
Data = (uint32_t) Data16;
} else if(Length == 4)
__asm__ __volatile__ ("inl %[address], %[value]" : [value] "=a" (Data) : [address] "d" (Port) :);
//else
//printf("Readport: Invalid length\r\n");
return Data;
}
uint32_t WritePort(uint16_t Port, uint32_t Data, int Length) {
if(Length == 1)
__asm__ __volatile__ ("outb %[value], %[address]" : : [value] "a" ((uint8_t) Data), [address] "d" (Port) :);
else if(Length == 2)
__asm__ __volatile__ ("outw %[value], %[address]" : : [value] "a" ((uint16_t) Data), [address] "d" (Port) :);
else if(Length == 4)
__asm__ __volatile__ ("outl %[value], %[address]" : : [value] "a" (Data), [address] "d" (Port) :);
//else
//printf("WritePort: Invalid length.\r\n");
return Data;
}
size_t ReadModelSpecificRegister(size_t MSR) {
size_t RegHigh = 0, RegLow = 0;
__asm__ __volatile__ ("rdmsr" : "=a" (RegLow), "=d" (RegHigh) : "c" (MSR) :);
return RegHigh << 32 | RegLow;
}
size_t WriteModelSpecificRegister(size_t MSR, size_t Data) {
size_t DataLow = 0, DataHigh = 0;
DataLow = ((uint32_t*) &Data)[0];
DataHigh = ((uint32_t*) &Data)[1];
__asm__ __volatile__ ("wrmsr" : : "a" (DataLow), "c" (MSR), "d" (DataHigh) :);
return Data;
}
uint32_t ReadVexMXCSR() {
uint32_t Data;
__asm__ __volatile__ ("vstmxcsr %[dest]" : [dest] "=m" (Data) : :);
return Data;
}
uint32_t WriteVexMXCSR(uint32_t Data) {
__asm__ __volatile__ ("vldmxcsr %[src]" : : [src] "m" (Data) :);
return Data;
}
uint32_t ReadMXCSR() {
uint32_t Data;
__asm__ __volatile__ ("stmxcsr %[dest]" : [dest] "=m" (Data) : :);
return Data;
}
uint32_t WriteMXCSR(uint32_t Data) {
__asm__ __volatile__ ("ldmxcsr %[src]" : : [src] "m" (Data) :);
return Data;
}
size_t ReadControlRegister(int CRX) {
size_t Data;
switch(CRX) {
case 0:
__asm__ __volatile__ ("mov %%cr0, %[dest]" : [dest] "=r" (Data) : :);
break;
case 1:
__asm__ __volatile__ ("mov %%cr1, %[dest]" : [dest] "=r" (Data) : :);
break;
case 2:
__asm__ __volatile__ ("mov %%cr2, %[dest]" : [dest] "=r" (Data) : :);
break;
case 3:
__asm__ __volatile__ ("mov %%cr3, %[dest]" : [dest] "=r" (Data) : :);
break;
case 4:
__asm__ __volatile__ ("mov %%cr4, %[dest]" : [dest] "=r" (Data) : :);
break;
case 8:
__asm__ __volatile__ ("mov %%cr8, %[dest]" : [dest] "=r" (Data) : :);
break;
case 'f':
__asm__ __volatile__ ("pushfq\n\t" "popq %[dest]" : [dest] "=r" (Data) : :);
break;
default:
break;
}
return Data;
}
size_t WriteControlRegister(int CRX, size_t Data) {
switch(CRX) {
case 0:
__asm__ __volatile__ ("mov %[dest], %%cr0" : : [dest] "r" (Data) : );
break;
case 1:
__asm__ __volatile__ ("mov %[dest], %%cr1" : : [dest] "r" (Data) : );
break;
case 2:
__asm__ __volatile__ ("mov %[dest], %%cr2" : : [dest] "r" (Data) : );
break;
case 3:
__asm__ __volatile__ ("mov %[dest], %%cr3" : : [dest] "r" (Data) : );
break;
case 4:
__asm__ __volatile__ ("mov %[dest], %%cr4" : : [dest] "r" (Data) : );
break;
case 8:
__asm__ __volatile__ ("mov %[dest], %%cr8" : : [dest] "r" (Data) : );
break;
case 'f':
__asm__ __volatile__ ("pushq %[dest]\n\t" "popfq" : : [dest] "r" (Data) : "cc");
break;
default:
break;
}
return Data;
}
size_t ReadExtendedControlRegister(size_t XCRX) {
size_t RegHigh = 0, RegLow = 0;
__asm__ __volatile__("xgetbv" : "=a" (RegLow), "=d" (RegHigh) : "c" (XCRX) :);
return (RegHigh << 32 | RegLow);
}
size_t WriteExtendedControlRegister(size_t XCRX, size_t Data){
__asm__ __volatile__("xsetbv" : : "a" ( ((uint32_t*) &Data)[0]), "c" (XCRX), "d" ( ((uint32_t*) &Data)[1] ) :);
return Data;
}
size_t ReadXCS() {
size_t Data;
__asm__ __volatile__("mov %%cs, %[dest]" : [dest] "=r" (Data) : :);
return Data;
}
DESC_TBL ReadGDT() {
DESC_TBL GDTData = {0};
__asm__ __volatile__("sgdt %[dest]" : [dest] "=m" (GDTData) : :);
return GDTData;
}
void WriteGDT(DESC_TBL GDTData) {
__asm__ __volatile__("lgdt %[src]" : : [src] "m" (GDTData) :);
}
DESC_TBL ReadIDT() {
DESC_TBL IDTData = {0};
__asm__ __volatile__("sidt %[dest]" : [dest] "=m" (IDTData) : :);
return IDTData;
}
void WriteIDT(DESC_TBL IDTData) {
__asm__ __volatile__("lidt %[src]" : : [src] "m" (IDTData) :);
}
uint16_t ReadLDT() {
uint16_t LDTData;
__asm__ __volatile__("sldt %[dest]" : [dest] "=m" (LDTData) : :);
return LDTData;
}
void WriteLDT(uint16_t LDTData) {
__asm__ __volatile__("lldt %[src]" : : [src] "m" (LDTData) :);
}
uint16_t ReadTSR() {
uint16_t TSRData;
__asm__ __volatile__("str %[dest]" : [dest] "=m" (TSRData) : :);
return TSRData;
}
void WriteTSR(uint16_t TSRData) {
__asm__ __volatile__("ltr %[src]" : : [src] "m" (TSRData) :);
}

40
chroma/system/serial.c Normal file
View File

@ -0,0 +1,40 @@
#include <kernel/chroma.h>
#define SERIAL_DATA(base) (base)
#define SERIAL_DLAB(base) (base + 1)
#define SERIAL_FIFO(base) (base + 2)
#define SERIAL_LINE(base) (base + 3)
#define SERIAL_MODEM(base) (base + 4)
#define SERIAL_LINE_STATUS(base) (base + 5)
#define COM1 0x3F8
void InitSerial() {
// Disable interrupts
WritePort(SERIAL_DLAB(COM1), 0x00, 1);
// Set baud rate to /3 (115200 bits/sec)
WritePort(SERIAL_LINE(COM1), 0x80, 1);
WritePort(SERIAL_DATA(COM1), 0x03, 1);
WritePort(SERIAL_DLAB(COM1), 0x00, 1);
// Set serial to 8 bits, no parity and one stop bit.
WritePort(SERIAL_LINE(COM1), 0x03, 1);
// Enable FIFO and clear all buffers
WritePort(SERIAL_FIFO(COM1), 0xC7, 1);
// Enable IRQs, set RTS and DSR
WritePort(SERIAL_MODEM(COM1), 0x03, 1);
}
int CheckSerial() {
return ReadPort(SERIAL_LINE_STATUS(COM1), 1);
}
void WriteSerialChar(const char chr) {
while(!(CheckSerial() & 0x20));
WritePort(COM1, chr, 1);
}
void WriteSerialString(const char* str, size_t len) {
for(size_t i = 0; i < len; i++) {
WriteSerialChar(str[i]);
}
}

264
chroma/video/draw.c Normal file
View File

@ -0,0 +1,264 @@
#include <kernel/chroma.h>
#include <kernel/video/bitmapfont.h>
#define FONT bitfont_latin
static size_t strlen(const char* String) {
size_t Len = 0;
while(String[Len] != '\0') {
Len++;
}
return Len;
}
typedef struct {
uint32_t charHeight;
uint32_t charWidth;
uint32_t charFGColor;
uint32_t charHLColor;
uint32_t charBGColor;
uint32_t minX;
uint32_t minY;
uint32_t charScale;
size_t charPosX;
size_t charPosY;
size_t charsPerRow;
size_t rowsPerScrn;
uint32_t scrlMode;
} PRINTINFO;
PRINTINFO PrintInfo = {0};
void InitPrint() {
PrintInfo.charHeight = 8;
PrintInfo.charWidth = 8;
PrintInfo.charFGColor = 0x00FFFFFF;
PrintInfo.charHLColor = 0x00000000;
PrintInfo.charBGColor = 0x00000000;
PrintInfo.charScale = 2;
PrintInfo.charPosX = 0;
PrintInfo.charPosY = 0;
PrintInfo.scrlMode = 0;
PrintInfo.charsPerRow = bootldr.fb_width / (PrintInfo.charScale * PrintInfo.charWidth) - 5;
PrintInfo.rowsPerScrn = bootldr.fb_height / (PrintInfo.charScale * PrintInfo.charHeight);
SerialPrintf("A single character is %ux%u pixels.\r\n", PrintInfo.charScale * PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charHeight);
SerialPrintf("The screen is %ux%u, meaning you can fit %ux%u characters on screen.\r\n", bootldr.fb_width, bootldr.fb_height, PrintInfo.charsPerRow, PrintInfo.rowsPerScrn);
}
static void DrawChar(const char character, size_t x, size_t y) {
x = x + PrintInfo.charPosX * (PrintInfo.charScale * PrintInfo.charWidth);
y = y + PrintInfo.charPosY * (PrintInfo.charScale * PrintInfo.charHeight);
uint32_t Y = PrintInfo.charWidth >> 3, X = 0;
if((PrintInfo.charWidth & 0x7) != 0) {
Y++;
}
for(uint32_t Row = 0; Row < PrintInfo.charHeight; Row++) {
for(uint32_t Bit = 0; Bit < PrintInfo.charWidth; Bit++) {
if ( ((Bit & 0x7) == 0) && (Bit > 0)) {
X++;
}
if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) {
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) {
size_t offset = ((y * bootldr.fb_width + x) +
PrintInfo.charScale * (Row * bootldr.fb_width + Bit) +
(ScaleY * bootldr.fb_width + ScaleX) +
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10;
// This one is crazy. Stick with me.
*(uint32_t* )(&fb + offset * 4)// Offset from the framebuffer, find the pixel..
// and find which column we need to be in. Multiply by 4 to navigate the 4bpp array,
= PrintInfo.charFGColor; // And set the color of the pixel.
}
}
} else {
// We need to draw the pixel transparently..
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) {
if(PrintInfo.charHLColor != 0xFF000000) {
size_t offset = ((y * bootldr.fb_width + x) +
PrintInfo.charScale * (Row * bootldr.fb_width + Bit) +
(ScaleY * bootldr.fb_width + ScaleX) +
PrintInfo.charScale * 1 * PrintInfo.charWidth) - 10;
if( y == 0 && x == 0){
SerialPrintf("Writing first pixel at %x\r\n", offset);
}
*(uint32_t*)(&fb + offset *4)
= PrintInfo.charHLColor;
}
}
}
}
}
}
/*
uint32_t Y = PrintInfo.charWidth >> 3, X = 0;
if((PrintInfo.charWidth & 0x7) != 0) {
Y++;
}
for(size_t CharRow = 0; CharRow < PrintInfo.charHeight; CharRow++) {
for(size_t CharPixel = 0; CharPixel < PrintInfo.charWidth; CharPixel++) {
if( CharPixel && (CharPixel & 0x7) == 0) {
X++;
}
for(size_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) {
for(size_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
if(FONT[character][CharRow * Y + X] >> (CharRow & 0x7) & 1) {
size_t offset = (y * bootldr.fb_width + x) +
(PrintInfo.charScale * (CharRow * bootldr.fb_width + CharPixel)) +
(ScaleY * (bootldr.fb_width + ScaleX));
*((uint32_t*) (&fb + offset * 4))
= PrintInfo.charFGColor;
//DrawPixel(x * PrintInfo.charWidth + X, Y + y + PrintInfo.charHeight, 0x00FF0000);
}
}
}
}
}
uint32_t Y = PrintInfo.charWidth >> 3, X = 0;
if((PrintInfo.charWidth & 0x7) != 0) {
Y++;
}
for(uint32_t Row = 0; Row < PrintInfo.charHeight; Row++) {
for(uint32_t Bit = 0; Bit < PrintInfo.charWidth; Bit++) {
if( ((Bit & 0x7) == 0) && (Bit > 0))
X++;
for(uint32_t ScaleY = 0; ScaleY < PrintInfo.charScale; ScaleY++) {
for(uint32_t ScaleX = 0; ScaleX < PrintInfo.charScale; ScaleX++) {
if((FONT[character][Row * Y + X] >> (Bit & 0x7)) & 1) {
size_t offset = (y * bootldr.fb_width + x) +
(PrintInfo.charScale * (Row * bootldr.fb_width + Bit)) +
(ScaleY * (bootldr.fb_width + ScaleX));
SerialPrintf("Drawing pixel at offset %x, at y %d, x %d, row %d, bit %d with scaley %d and scalex %d. charScale %d and charWidth %d, making a charLength %d.\r\n", offset, y, x, Row, Bit, ScaleX, ScaleY, PrintInfo.charScale, PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charWidth);
*((uint32_t*) (&fb + offset * 4))
= PrintInfo.charFGColor;
} else {
if(PrintInfo.charHLColor != 0xFF000000) {
size_t offset = (y * bootldr.fb_width + x) +
(PrintInfo.charScale * (Row * bootldr.fb_width + Bit)) +
(ScaleY * (bootldr.fb_width + ScaleX));
SerialPrintf("Drawing pixel at offset %x\r\n", offset);
*((uint32_t*) (&fb + offset * 4))
= PrintInfo.charHLColor;
}
}
}
}
}
}
*/
}
void DrawPixel(uint32_t x, uint32_t y, uint32_t color) {
if(x > bootldr.fb_width) {
DrawPixel(x - bootldr.fb_width, y + (PrintInfo.charHeight * PrintInfo.charScale), color);
//FillScreen(color);
} else if(y > bootldr.fb_height) {
DrawPixel(x, y - bootldr.fb_height, color);
} else {
*((uint32_t*) (&fb + (y * bootldr.fb_scanline + x) * 4)) = color;
SerialPrintf("Drawing a pixel at %d, %d with color 0x%x\r\n", x, y, color);
}
}
void FillScreen(uint32_t color) {
for(size_t y = 0; y < bootldr.fb_height; y++) {
for(size_t x = 0; x < bootldr.fb_width; x++) {
DrawPixel(x, y, color);
}
}
}
static void ProgressCursorS(size_t Steps) {
if(PrintInfo.charPosX + Steps > PrintInfo.charsPerRow) {
PrintInfo.charPosX = 0;
size_t Rows = Steps / PrintInfo.charsPerRow;
if(PrintInfo.charPosY + Rows > PrintInfo.rowsPerScrn) {
size_t RowsLeft = PrintInfo.rowsPerScrn - PrintInfo.charPosY;
ProgressCursorS((Rows - RowsLeft) * PrintInfo.charsPerRow);
} else {
PrintInfo.charPosY++;
}
} else {
PrintInfo.charPosX += Steps;
}
}
static void Newline() {
ProgressCursorS(PrintInfo.charsPerRow);
}
static void ProgressCursor() {
ProgressCursorS(1);
}
void WriteChar(const char character) {
//size_t y = PrintInfo.charPos / RowsWidth * (PrintInfo.charScale * PrintInfo.charHeight);
//size_t x = (PrintInfo.charPos % RowsWidth) * (PrintInfo.charScale * PrintInfo.charWidth);
switch(character) {
case '\b':
if(PrintInfo.charPosX - 1 == 0) {
if(PrintInfo.charPosY - 1 == 0) {
PrintInfo.charPosY = 0;
} else {
PrintInfo.charPosY--;
}
} else {
PrintInfo.charPosX = 0;
}
break;
case '\n':
Newline();
break;
default:
DrawChar(character, PrintInfo.charPosX, PrintInfo.charPosY);
ProgressCursor();
break;
}
}
void WriteString(const char* string) {
for(int i = 0; i < strlen(string); i++) {
WriteChar(string[i]);
}
}

109
chroma/video/print.c Normal file
View File

@ -0,0 +1,109 @@
#include <kernel/chroma.h>
static size_t strlen(const char* String) {
size_t Len = 0;
while(String[Len] != '\0') {
Len++;
}
return Len;
}
static void NumToStr(char* Buffer, size_t Num, size_t Base) {
size_t Temp, i = 0, j = 0;
do {
Temp = Num % Base;
Buffer[i++] = (Temp < 10) ? (Temp + '0') : (Temp + 'a' - 10);
} while (Num /= Base);
Buffer[i--] = 0;
for(j = 0; j < i; j++, i--) {
Temp = Buffer[j];
Buffer[j] = Buffer[i];
Buffer[i] = Temp;
}
}
int SerialPrintf(const char* restrict Format, ...) {
va_list Parameters;
va_start(Parameters, Format);
int CharsWritten = 0;
size_t Base, Num;
char BufferStr[512] = {0};
while(*Format != '\0') {
size_t Limit = UINT64_MAX - CharsWritten;
if(*Format == '%') {
if(*(++Format) == '%')
Format++;
switch(*Format) {
case 'c':
Format++;
char c = (char) va_arg(Parameters, int);
WriteSerialString(&c, sizeof(c));
CharsWritten++;
break;
case 's':
Format++;
const char* Str = va_arg(Parameters, char*);
size_t Len = strlen(Str);
if(Limit < Len)
return -1;
WriteSerialString(Str, Len);
CharsWritten += Len;
break;
case 'd':
case 'u':
case 'p':
case 'x':
Num = va_arg(Parameters, size_t);
Base = 0;
if(*Format == 'd' || *Format == 'u') {
Base = 10; // Decimal & Unsigned are base 10
} else {
Base = 16; // Hex and Ptr are base 16
}
Format++;
NumToStr(BufferStr, Num, Base);
Len = strlen(BufferStr);
WriteSerialString(BufferStr, Len);
CharsWritten += Len;
break;
//case 'p':
//uint8_t Base = 16;
//size_t Dest = (uintptr_t) va_arg(Parameters, void*);
default:
WriteSerialString("%u", 2);
break;
}
} else {
WriteSerialChar(*Format);
Format++;
}
}
va_end(Parameters);
return CharsWritten;
}

61
chroma/video/tty.c Normal file
View File

@ -0,0 +1,61 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <kernel/video/tty.h>
#include <kernel/video/vga-textmode.h>
static const size_t TERM_WIDTH = 80;
static const size_t TERM_HEIGHT = 25;
size_t TERM_ROW;
size_t TERM_COL;
uint8_t TERM_COLOR;
uint16_t* TERM_BUFFER;
void Term_Init(void) {
TERM_ROW = 0;
TERM_COL = 0;
TERM_COLOR = VGACharColor(VGA_COLOR_LIGHTGREY, VGA_COLOR_BLACK);
TERM_BUFFER = (uint16_t*) 0xB8000;
for(size_t y = 0; y < TERM_HEIGHT; y++) {
for(size_t x = 0; x < TERM_WIDTH; x++) {
const size_t index = y * TERM_WIDTH + x;
TERM_BUFFER[index] = VGAChar(' ', TERM_COLOR);
}
}
}
void Term_SetColor(uint8_t color) {
TERM_COLOR = color;
}
void Term_PutVGAChar(char c, uint8_t color, size_t x, size_t y) {
const size_t index = y * TERM_WIDTH + x;
TERM_BUFFER[index] = VGAChar(c, color);
}
void Term_PutChar(char c) {
Term_PutVGAChar(c, TERM_COLOR, TERM_COL, TERM_ROW);
if(++TERM_COL == TERM_WIDTH) {
TERM_COL = 0;
if(++TERM_ROW == TERM_HEIGHT)
TERM_ROW = 0;
}
}
void Term_Write(const char* str, size_t len) {
for(size_t i = 0; i < len; i++)
Term_PutChar(str[i]);
}
void Term_WriteString(const char* str) {
Term_Write(str, strlen(str));
}

BIN
iso/boot/bootloader Normal file

Binary file not shown.

4
iso/boot/grub/grub.cfg Normal file
View File

@ -0,0 +1,4 @@
menuentry "Sync" {
multiboot /boot/bootloader
module /boot/initrd
}

31
linker.ld Normal file
View File

@ -0,0 +1,31 @@
mmio = 0xfffffffff8000000;
fb = 0xfffffffffc000000;
PHDRS
{
boot PT_LOAD;
}
SECTIONS
{
. = 0xffffffffffe00000;
bootldr = .; . += 4096;
environment = .; . += 4096;
.text : {
KEEP(*(.text.boot)) *(.text .text.*)
*(.rodata .rodata.*)
*(.data .data.*)
} :boot
.bss (NOLOAD) : {
. = ALIGN(16);
*(.bss .bss.*)
*(COMMON)
} :boot
/DISCARD/ : { *(.eh_frame) *(.comment) }
end = .;
}