feat: TrueType (TTF) font rendering, many new desktop applications and DOOM support, among other improvements

This commit is contained in:
2026-02-20 22:46:41 +01:00
parent 40b596c0d3
commit 9e191f64a9
123 changed files with 9021 additions and 355 deletions
+20 -2
View File
@@ -1,18 +1,30 @@
;
; Context.asm
; Context switch: save/restore callee-saved registers, stack pointer, and CR3
; Context switch: save/restore callee-saved registers, stack pointer, CR3, and FPU state
; Copyright (c) 2025 Daniel Hammer
;
[bits 64]
section .text
; void SchedContextSwitch(uint64_t* oldRsp, uint64_t newRsp, uint64_t newCR3)
; void SchedContextSwitch(uint64_t* oldRsp, uint64_t newRsp, uint64_t newCR3,
; uint8_t* oldFpuArea, uint8_t* newFpuArea)
; rdi = pointer to save old RSP
; rsi = new RSP to restore
; rdx = new PML4 physical address (for CR3)
; rcx = old FPU state area (may be null)
; r8 = new FPU state area (may be null)
global SchedContextSwitch
SchedContextSwitch:
; Save FPU state before pushing registers (rcx/r8 are caller-saved)
test rcx, rcx
jz .skip_fxsave
fxsave [rcx]
.skip_fxsave:
; Stash r8 in r9 (callee-saved registers will clobber r8 slot on stack)
mov r9, r8
; Save callee-saved registers on the current stack
push rbp
push rbx
@@ -42,4 +54,10 @@ SchedContextSwitch:
pop rbx
pop rbp
; Restore FPU state
test r9, r9
jz .skip_fxrstor
fxrstor [r9]
.skip_fxrstor:
ret
+30 -7
View File
@@ -14,9 +14,11 @@
#include <CppLib/Stream.hpp>
#include <Hal/Apic/Apic.hpp>
#include <Hal/GDT.hpp>
#include <Api/WinServer.hpp>
// Assembly: context switch with CR3 parameter
extern "C" void SchedContextSwitch(uint64_t* oldRsp, uint64_t newRsp, uint64_t newCR3);
// Assembly: context switch with CR3 and FPU state parameters
extern "C" void SchedContextSwitch(uint64_t* oldRsp, uint64_t newRsp, uint64_t newCR3,
uint8_t* oldFpuArea, uint8_t* newFpuArea);
// Assembly: jump to user mode via IRETQ
extern "C" void JumpToUserMode(uint64_t rip, uint64_t rsp);
@@ -66,7 +68,7 @@ namespace Sched {
for (int i = 0; i < MaxProcesses; i++) {
processTable[i].pid = i;
processTable[i].state = ProcessState::Free;
processTable[i].name = nullptr;
processTable[i].name[0] = '\0';
processTable[i].savedRsp = 0;
processTable[i].stackBase = 0;
processTable[i].entryPoint = 0;
@@ -191,7 +193,11 @@ namespace Sched {
Process& proc = processTable[slot];
proc.pid = nextPid++;
proc.state = ProcessState::Ready;
proc.name = vfsPath;
{
int i = 0;
for (; i < 63 && vfsPath[i]; i++) proc.name[i] = vfsPath[i];
proc.name[i] = '\0';
}
proc.savedRsp = (uint64_t)sp;
proc.stackBase = (uint64_t)kernelStackBase;
proc.entryPoint = entry;
@@ -224,6 +230,11 @@ namespace Sched {
proc.termCols = 0;
proc.termRows = 0;
// Initialize FPU state: zero out, then set default FCW and MXCSR
memset(proc.fpuState, 0, 512);
*(uint16_t*)&proc.fpuState[0] = 0x037F; // FCW: default x87 control word
*(uint32_t*)&proc.fpuState[24] = 0x1F80; // MXCSR: default SSE control/status
return proc.pid;
}
@@ -276,7 +287,9 @@ namespace Sched {
// Update TSS RSP0 for hardware interrupts from ring 3
Hal::g_tss.rsp0 = processTable[next].kernelStackTop;
SchedContextSwitch(oldRspPtr, processTable[next].savedRsp, newCR3);
uint8_t* oldFpu = (currentPid >= 0) ? processTable[currentPid].fpuState : nullptr;
uint8_t* newFpu = processTable[next].fpuState;
SchedContextSwitch(oldRspPtr, processTable[next].savedRsp, newCR3, oldFpu, newFpu);
}
void Tick() {
@@ -309,6 +322,9 @@ namespace Sched {
return;
}
// Clean up any windows owned by this process
WinServer::CleanupProcess(processTable[currentPid].pid);
processTable[currentPid].state = ProcessState::Terminated;
int next = -1;
@@ -329,11 +345,13 @@ namespace Sched {
g_kernelRsp = processTable[next].kernelStackTop;
Hal::g_tss.rsp0 = processTable[next].kernelStackTop;
SchedContextSwitch(&processTable[old].savedRsp, processTable[next].savedRsp, newCR3);
SchedContextSwitch(&processTable[old].savedRsp, processTable[next].savedRsp, newCR3,
processTable[old].fpuState, processTable[next].fpuState);
} else {
int old = currentPid;
currentPid = -1;
SchedContextSwitch(&processTable[old].savedRsp, idleSavedRsp, GetKernelCR3());
SchedContextSwitch(&processTable[old].savedRsp, idleSavedRsp, GetKernelCR3(),
processTable[old].fpuState, nullptr);
}
for (;;) {
@@ -362,4 +380,9 @@ namespace Sched {
return nullptr;
}
Process* GetProcessSlot(int slot) {
if (slot < 0 || slot >= MaxProcesses) return nullptr;
return &processTable[slot];
}
}
+7 -1
View File
@@ -30,7 +30,7 @@ namespace Sched {
struct Process {
int pid;
ProcessState state;
const char* name;
char name[64];
uint64_t savedRsp;
uint64_t stackBase; // Bottom of allocated kernel stack (lowest address)
uint64_t entryPoint;
@@ -58,6 +58,9 @@ namespace Sched {
// GUI terminal dimensions (set by desktop, read by SYS_TERMSIZE)
int termCols = 0;
int termRows = 0;
// FPU/SSE state (FXSAVE format, must be 16-byte aligned)
uint8_t fpuState[512] __attribute__((aligned(16)));
};
void Initialize();
@@ -82,4 +85,7 @@ namespace Sched {
// Find a process by PID (returns nullptr if not found or not alive)
Process* GetProcessByPid(int pid);
// Get a pointer to slot i in the process table (for enumeration)
Process* GetProcessSlot(int slot);
}