Skip to content

cupidthecat/cupid-os

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

279 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cupid-os

32-bit x86 hobby OS written in C and NASM. Has a graphical desktop, window manager, built-in C compiler, assembler, and scripting language. Runs on real hardware or QEMU. Inspired by TempleOS, OsakaOS, and Unix.

Desktop File manager Paint

What it has

  • VBE 640x480 32bpp graphics with a window manager, taskbar, and desktop icons
  • CupidC, a HolyC-inspired C compiler with JIT and ELF32 AOT output
  • Hardware FPU (x87) and SSE/SSE2 with eager FXSAVE context switch
  • CupidC float/double scalars and float4/double2 SIMD types with SSE intrinsics
  • libm: 25 operations (sqrt, sin, cos, tan, atan, atan2, exp, exp2, log, log2, pow, asin, acos, sinh, cosh, tanh, cbrt, hypot, nextafter, fabs, floor, ceil, round, trunc, fmod + f-variants)
  • printf %f, %e, %g, %.Nf with x87-backed int/fractional split
  • #NM/#MF/#XF FPU exception handlers with MXCSR/FSW/FCW dump
  • CupidASM, an Intel-syntax x86-32 assembler with JIT and ELF32 AOT output
  • CupidScript, a shell scripting language with pipes, redirects, and job control
  • 73 built-in shell programs with history, tab completion, pipes, and redirects
  • VFS with RamFS (/), DevFS (/dev), FAT16 (/disk), and persistent homefs (/home)
  • Opt-in swap: handle-based disk-backed memory extension with 4 size classes (1K/4K/16K/64K), true LRU eviction, up to 1024 handles over a 16 MB FAT16 swap file.
  • ISO9660 readonly mount with Rock Ridge (SUSP/RRIP) long filenames, multi-mount (up to 4), case-insensitive lookup; mount .iso files from the VFS via mount foo.iso /iso
  • Preemptive round-robin scheduler, up to 32 kernel threads
  • Process domains in scheduler and ps output (kernel/hosted/external)
  • Two-stage bootloader that loads the kernel above 1MB via unreal mode
  • GUI apps: Notepad, Terminal with ANSI colors, Paint, Calendar, File Manager
  • 64-entry LRU disk block cache with write-back policy
  • 6 GUI themes: Windows95, Pastel Dream, Dark Mode, High Contrast, Retro Amber, Vaporwave
  • USB 1.1 + 2.0: UHCI + EHCI host controllers with HID keyboard/mouse, hub class (depth ≤ 5), and mass storage (BBB + SCSI)
  • SMP up to 32 CPUs: ACPI/MP discovery, per-CPU LAPIC timer, big kernel lock, IPI-based reschedule and cross-CPU call
  • Networking: RTL8139 + E1000 drivers, ARP / IPv4 / ICMP / UDP / TCP (client + server), DHCP with static fallback, DNS resolver, BSD-style sockets
  • Headless build (make run-headless): boots straight into shell over COM1/stdio, no VBE — scriptable with run-tests.sh
  • PS/2 keyboard and mouse, ATA/IDE disk, RTC, serial, PC speaker drivers
  • System clipboard, x86-32 disassembler, BMP image codec

Recent additions

Six feature tracks landed on top of the GUI/compiler/shell base, each with a design spec, implementation plan, and subagent-driven tasks with per-task code review. Specs and plans live under docs/superpowers/specs/ and docs/superpowers/plans/; each track also ships a wiki/*.md page and an embedded cupidos-txt/*.CTXT doc rendered live by notepad.

  • FPU + SSE + float in CupidC — x87 init, FXSAVE/FXRSTOR on context switch, MXCSR defaults, #NM/#MF/#XF exception handlers with register dump. CupidC gains float, double, float4, and double2 with SSE intrinsics; 25-operation libm; printf %f %e %g %.Nf with x87-backed int/fractional split.
  • ISO9660 read-only mountmount foo.iso /iso from any file on the VFS; Rock Ridge (SUSP/RRIP) long filenames; case-insensitive lookup; up to 4 simultaneous mounts.
  • Opt-in handle-based swap — 4 size classes (1K/4K/16K/64K), true LRU eviction, 1024 handles over a 16 MB FAT-backed swap file; explicit swap_alloc / pin / unpin rather than VM page faults.
  • USB 1.1 + 2.0 stack — UHCI + EHCI controllers sharing an IRQ dispatcher, device enumeration, HID keyboard and mouse, hub class (depth ≤ 5), and mass storage (BBB + SCSI) layered under FAT16.
  • SMP up to 32 CPUs — ACPI/MP discovery, INIT-SIPI-SIPI AP bringup, per-CPU LAPIC timers, IOAPIC routing with the 8259 fully masked, ticket-based big kernel lock, shared runqueue, IPI reschedule / cross-CPU call / panic broadcast.
  • Full TCP/IP networking — RTL8139 and E1000 drivers, ARP + IPv4 + ICMP + UDP + TCP (RFC 793 subset, client and server), DHCP client with static fallback, DNS resolver with 16-entry TTL cache, and a 32-slot BSD socket table exposed to both the shell and CupidC.

Built-in CupidC smoke tests exercise each track: feature12_float, feature13_double, feature14_simd, feature15_libm, feature16_asm_fpu (float/SIMD/libm), feature17_iso (ISO9660), feature18_swap (swap), feature19_usb (USB), feature20_smp (SMP), feature21_net (TCP client — DNS + connect + HTTP GET), feature22_net_server (TCP listen + accept + echo).

Feature demo quickstart

After make run, these shell commands exercise the major subsystems:

# 1) Filesystems and persistence
mount
ls /
ls /home
mkdir /home/demo
echo hello > /home/demo/hello.txt
cat /home/demo/hello.txt

# 2) Processing and scheduling
ps
time ls /

# 3) Shell features: pipes, redirects, history
ls /bin | grep gfx > /home/demo/gfx.txt
cat /home/demo/gfx.txt
history

# 4) CupidC JIT and language features
feature1_types
feature3_class
feature10_repl
feature11_ternary

# 5) CupidASM demo execution
as /demos/hello.asm
as /demos/syscall_vfs_extended_demo.asm
as /demos/simd_blur.asm        # SSE + SIMD
as /demos/fpu_kernel.asm       # x87 + SSE assembly

# 6) GUI apps and graphics
terminal
notepad
fm
paint
gfxdemo
gfxtest

# 7) Introspection and debugging tools
sysinfo
registers
memstats
stacktrace
logdump

# 8) Audio/speaker demos
godsong
godspeak

# 9) FPU + SSE float, libm, SIMD
feature12_float
feature13_double
feature14_simd
feature15_libm
feature16_asm_fpu

# 10) ISO9660 read-only mount
mount disk.iso /iso
ls /iso
feature17_iso

# 11) Opt-in handle-based swap
feature18_swap

# 12) USB (run under make run-usb for a populated stick)
feature19_usb

# 13) SMP introspection
smp
feature20_smp

# 14) Networking
ifconfig
arp
ping 10.0.2.2
resolve example.com
netstat
feature21_net           # TCP client: DNS + connect + HTTP GET
feature22_net_server    # TCP server: listen + accept + echo
cupidfetch              # one-shot HTTP GET

Philosophy

All code runs in ring 0. No privilege separation, no virtual memory isolation, no artificial restrictions. User programs have direct hardware access, full memory access, and can call any kernel function. The point is transparency and learning, not security. If you want to understand what your computer is actually doing, this is the kind of environment that lets you do that.

The design borrows from TempleOS (single address space, built-in compiler, bare metal), Unix (VFS, shell, process model), and OsakaOS (aesthetics).

Building

Requires NASM, GCC with 32-bit support, GNU Make, QEMU, and mtools.

sudo apt-get install nasm gcc gcc-multilib make qemu-system-x86 mtools
make               # builds cupidos.img
make run           # boots in QEMU with SDL graphics
make run-log       # boots and writes serial output to debug.log
make run-headless  # boots straight into shell over stdio (scriptable tests)
make run-usb       # UHCI + EHCI + kbd/mouse + FAT16 USB stick
make run-net-debug # dumps every TX/RX frame over serial

Default image size is 200MB. To change it:

make HDD_MB=100

Make targets

Target What it does
make Build the full disk image
make run Boot in QEMU with SDL graphics
make run-log Boot in QEMU, write serial to debug.log
make run-headless Boot headless shell over stdio (no VBE) — scriptable
make run-usb Boot with UHCI + EHCI + a 32 MB FAT16 USB stick
make run-net-debug Dump every TX/RX frame over serial
make sync-demos Copy demos/*.asm into the FAT16 partition
make clean Remove object files, keep cupidos.img
make clean-image Remove cupidos.img only
make distclean Remove everything including cupidos.img

A run-tests.sh harness wraps make run-headless, feeds a batch of commands over COM1, and parses PASS/FAIL sentinels — used for CupidC/CupidASM regression checks in CI or local sanity runs.

Copying files into /home

CupidOS now mounts FAT16 at /disk and mounts persistent homefs at /home.

  • /disk is the raw FAT16 partition in cupidos.img.
  • /home is homefs, serialized into HOMEFS.SYS on FAT16.
  • On first boot without HOMEFS.SYS, homefs imports existing FAT16 files.

The FAT16 partition sits at byte offset 2097152 (4096 * 512) inside cupidos.img. Use mtools to put files in the FAT16 backend:

mcopy -o -i cupidos.img@@2097152 myfile.txt ::/myfile.txt
mdir  -i cupidos.img@@2097152 ::/

If you change FAT_START_LBA in the Makefile, recalculate: offset = FAT_START_LBA * 512.

Debugging

GDB remote debug:

qemu-system-i386 -s -S -boot c -hda cupidos.img &
gdb
(gdb) target remote localhost:1234
(gdb) break *0x100000
(gdb) continue

QEMU monitor is at Ctrl+Alt+2. Serial output comes through stdout on make run.


Project layout

cupid-os/
  boot/           two-stage BIOS bootloader
  kernel/         kernel source (104 C files + headers/asm)
  drivers/        hardware drivers (9 C files)
  bin/            built-in CupidC programs (88 .cc files)
  demos/          CupidASM demo programs (21 .asm files)
  user/           example ELF user programs and cupid.h header
  wiki/           documentation (28 Markdown files)
  docs/superpowers/  additional project docs
  cupidos-txt/    embedded rich-text docs (.CTXT format)
  img/            screenshots
  link.ld         linker script
  Makefile

Bootloader (boot/boot.asm)

Two stages, about 4KB total.

Stage 1 lives in the MBR at 0x7C00. It loads stage 2 (4 sectors from LBA 1) to 0x7E00 using INT 0x13 EDD, then jumps there.

Stage 2 does the real work:

  • Enables the A20 gate
  • Switches to unreal mode so it can write above 1MB while still in 16-bit real mode
  • Probes VBE and sets mode 0x118 (640x480x32bpp linear framebuffer)
  • Loads the kernel in 127-sector chunks from LBA 5 to physical address 0x100000
  • Sets up 4KB page tables, identity-mapping 0 to 32MB
  • Loads the GDT, enables protected mode, jumps to _start

Disk layout:

LBA 0       MBR / Stage 1
LBA 1-4     Stage 2
LBA 5-4095  Kernel binary (up to ~2MB)
LBA 4096+   FAT16 partition (mounted as /disk)
           homefs persistent container (HOMEFS.SYS), mounted as /home

Kernel (kernel/)

Core

File What it does
kernel.c/.h kmain() entry, initializes IDT/GDT/PIC/PIT/keyboard/mouse/VBE, starts desktop
idt.c/.h IDT setup, 256 gate descriptors
irq.c/.h IRQ dispatch, handler registration
pic.c/.h 8259 PIC init, IRQ masking, EOI
panic.c/.h Kernel panic with register dump and stack trace
ports.h inb/outb/inw/outw port I/O macros
assert.h Assert macros

Memory

File What it does
memory.c/.h Physical memory manager, bitmap allocator over the first 32MB, kernel heap
paging.c Page tables, identity-mapped address space

The kernel heap uses a bump allocator with a free list. Everything runs at ring 0 in a flat 32-bit address space. The stack lives from 0x800000 to 0x880000 (grows down, 512KB).

Processes

File What it does
process.c/.h PCB, process list, round-robin scheduler
context_switch.asm Saves EBX/ESI/EDI/EBP/EFLAGS, swaps ESP/EIP

Up to 32 threads. Scheduler is preemptive, driven by IRQ0 at 200Hz (5ms slices). Process states: running, ready, blocked, zombie. Primitives: spawn(), exit(), wait().

Filesystem

File What it does
vfs.c/.h VFS layer: open, read, write, close, seek, stat, readdir
vfs_helpers.c/.h read_all(), write_all(), read_text(), write_text()
ramfs.c/.h In-memory root filesystem, populated at boot with programs/docs/demos
devfs.c/.h /dev entries: null, zero, console, serial, random
fat16.c/.h FAT16: MBR parsing, cluster chains, file read/write/create
fat16_vfs.c/.h FAT16 to VFS adapter
homefs.c/.h Persistent logical filesystem for /home, serialized to HOMEFS.SYS
blockdev.c/.h Block device abstraction
blockcache.c/.h 64-entry LRU sector cache, write-back, flushes periodically

Filesystem layout at runtime:

/           RamFS, ephemeral, rebuilt each boot
  bin/      built-in CupidC programs
  demos/    CupidASM demo programs
  docs/     documentation
  dev/      DevFS: null, zero, console, serial, random
  disk/     FAT16 raw partition view
  home/     homefs persistent user data (backed by HOMEFS.SYS on FAT16)

Graphics

File What it does
graphics.c/.h Pixel, line, rect primitives with clipping
gfx2d.c/.h Gradients (H/V/radial), shadows, dither, alpha blending, file dialogs
gfx2d_effects.c/.h Blur, sharpen, sepia, noise, color manipulation
gfx2d_icons.c/.h Desktop icon registration, hit-testing, drag and drop
gfx2d_assets.c/.h Texture loading and caching
gfx2d_transform.c/.h Scale, rotate, skew, perspective
font_8x8.c/.h 8x8 bitmap font data and renderer
bmp.c/.h BMP codec: 24-bit uncompressed read/write, 32bpp output

All rendering goes to a RAM back buffer first. vga_flip() copies it to the linear framebuffer. Double-buffered so there's no tearing.

GUI

File What it does
gui.c/.h Window list, z-order, drag, focus, minimize, close (up to 16 windows)
gui_widgets.c/.h Checkboxes, radio buttons, dropdowns, sliders, progress bars
gui_containers.c/.h Panels, tabs, splitters, groups
gui_menus.c/.h Menu bars, dropdown menus, context menus, toolbars, status bars, tooltips
gui_themes.c/.h 6 built-in themes, .theme file load/save
gui_events.c/.h Mouse, keyboard, and window event dispatch
ui.c/.h Higher-level controls on top of the widget layer

Themes include Windows95, Pastel Dream, Dark Mode, High Contrast, Retro Amber, and Vaporwave. Theme files can be saved and loaded from disk.

Desktop

desktop.c/.h handles the desktop shell: animated gradient background, taskbar with clock, icon grid, and the main event loop. On mouse-move it only redraws the cursor, not the whole screen. The background color LUT is recalculated at most every 3-4 animation frames.

Apps

File What it does
notepad.c/.h Text editor with menus, scrollbars, clipboard, undo/redo, file open/save
terminal_app.c/.h GUI terminal window: scrolling text buffer, PS/2 input, ANSI color support
terminal_ansi.c/.h ANSI escape sequence parser: colors, cursor positioning, screen clear
calendar.c/.h Date/time math, RTC integration, taskbar clock, calendar popup
clipboard.c/.h System clipboard, shared across Notepad and Terminal
ed.c/.h Original line editor in C, superseded by ed.cc

Compilers and languages

CupidC (cupidc*.c) is a HolyC-inspired C dialect:

  • Single-pass recursive descent compiler
  • JIT mode: compile and run .cc files in memory immediately
  • AOT mode: compile to ELF32 binaries on disk
  • Inline assembly, structs up to 16 fields, full ring-0 kernel bindings
  • Limits: 128KB code, 32KB data, 256 functions, 512 symbols per unit

CupidASM (as*.c) is an Intel-syntax x86-32 assembler:

  • 62 mnemonics, 24 registers (8/16/32-bit)
  • JIT and AOT (ELF32) modes
  • Directives: INCLUDE, RESERVE, alignment
  • Forward references, up to 512 labels
  • Kernel bindings for print, malloc, VFS, graphics calls

CupidScript (cupidscript*.c) is a bash-like scripting language (.cup files):

  • Variables, if/else, while, for loops
  • Functions with parameters and return values
  • Pipes (|), redirects (> and >>), background jobs (&)
  • Arrays, string operations
  • Calls shell commands and kernel functions directly

CupidDis (dis.c/.h) is an x86-32 disassembler used for debugging.

Program execution

File What it does
exec.c/.h ELF32 loader: program headers, BSS zeroing, relocation
syscall.c/.h Syscall table passed to ELF programs as a struct of function pointers

Shell (kernel/shell.c)

The shell handles command parsing, pipelines, input/output redirection, background jobs, history with arrow-key navigation, and tab completion. Typing a .cc filename runs it through CupidC JIT. Typing a .asm file runs it through CupidASM JIT. Typing a .cup file runs it through CupidScript.

Utility libraries

File What it does
string.c/.h strlen, strcmp, strcpy, strcat, strtok, strstr, sprintf and more
math.c/.h 64-bit integer math, g2d_isqrt(), trig approximations, itoa/atoi

Drivers (drivers/)

File What it does
vga.c/.h VBE 640x480x32bpp, double-buffering, vsync via Y_OFFSET page flip
keyboard.c/.h PS/2 keyboard on IRQ1, scancode to ASCII, modifiers, key repeat, circular buffer
mouse.c/.h PS/2 mouse on IRQ12, 3-byte packet parsing, scroll wheel, cursor
pit.c/.h 8254 PIT channel 0 at 200Hz, channel 2 for speaker
timer.c/.h Tick counter, sleep(), multi-channel timer callbacks
speaker.c/.h PC speaker beep via port 0x61
ata.c/.h ATA/IDE PIO, 28-bit LBA, IDENTIFY, read/write on primary channel
rtc.c/.h Real-time clock from CMOS, BCD to binary, NMI masking
serial.c/.h COM1 at 115200 baud, used for kernel debug output

Built-in programs (bin/)

88 CupidC programs embedded in RamFS at boot, all directly runnable from the shell:

Category Programs
Core shell/filesystem cat, cd, cp, find, grep, ls, mkdir, mount, mv, pwd, rm, rmdir, sync, touch
Text/console clear, echo, ed, printc, resetcolor, setcolor
Process/system date, help, history, kill, ps, reboot, spawn, sysinfo, time, yield
Introspection/debug cachestats, crashtest, logdump, loglevel, registers, stacktrace
Memory tools memcheck, memdump, memleak, memstats
GUI/graphics apps bgstudio, bmptest, fm, gfxdemo, gfxgui_test, gfxtest, notepad, paint, terminal
Audio/speech godsong, godspeak
CupidC language tests cupidc_test1-5, feature1_types, feature2_top_level, feature3_class, feature4_forward_calls, feature5_print_builtin, feature6_exe, feature7_new_del, feature8_reg_noreg, feature9_abs_addr, feature10_repl, feature11_ternary
FPU/SSE/libm tests feature12_float, feature13_double, feature14_simd, feature15_libm, feature16_asm_fpu, fp_drill
Subsystem smoke tests feature17_iso (ISO9660), feature18_swap (swap), feature19_usb (USB), feature20_smp (SMP), feature21_net (TCP client), feature22_net_server (TCP server)
Networking utilities cupidfetch
Legacy compiler experiments old_cc2, old_cc2_single
Text/documentation viewers auto, bible, oracle
Test programs test, test_print
Misc utility ctxt

Assembly demos (demos/)

21 CupidASM programs embedded in RamFS. Run with as <name>.asm from the shell:

hello, loop, fibonacci, factorial, bubblesort, stack, data, math, include_feature, include_helper, jcc_aliases, asm_compat_reserve, reserve_directives, fs_syscalls, syscall_table_demo, syscall_vfs_extended_demo, parity_core, parity_diag, parity_gfx2d, fpu_kernel, simd_blur


User programs (user/)

The user/ directory has example ELF32 programs (hello.c, cat.c, ls.c) and user/cupid.h which defines the syscall table ABI. Use cupid.h when writing programs that get compiled to ELF and loaded by the kernel.


Memory layout

0x007C00            Stage 1 bootloader (512 bytes)
0x007E00            Stage 2 bootloader (2KB)
0x100000            Kernel start (_start)
                    .text, .rodata, .data (2MB max)
                    .bss
0x400000            CupidC JIT region (128KB code + 32KB data)
0x500000            CupidASM JIT region (128KB code + 32KB data)
0x800000            Stack guard page
0x800000-0x880000   Kernel stack (512KB, grows down)
0xE0000000+         VBE linear framebuffer (address comes from BIOS)

Interrupt handling

256-entry IDT. CPU exceptions are entries 0-31. IRQs start at 32 (PIC remapped).

IRQ Source
IRQ0 (32) PIT timer at 200Hz, drives scheduler, animation, and clock
IRQ1 (33) PS/2 keyboard
IRQ12 (44) PS/2 mouse

Exceptions print a register dump and stack trace before halting.


Performance notes

Changes made in the 2026-02-16 optimization pass:

  • Added g2d_isqrt() to replace while(k*k<j) k++ patterns throughout graphics code
  • gfx2d_gradient_v now uses g2d_fill32 for row fills instead of a per-pixel loop
  • gfx2d_gradient_radial pre-clips the draw bounds and writes directly to the framebuffer pointer
  • gfx2d_shadow is now single-pass instead of a blur x width x height triple loop
  • vga_clear_screen uses an 8-pixel unrolled store loop
  • desktop_redraw_cycle has a cursor-only path that skips full repaints on mouse moves
  • Background animation LUT recalculates at most every 3-4 frames
  • vga_retrace_timeout reduced from 1,000,000 to 50,000 cycles (was blocking up to 100ms)
  • PIT raised from 100Hz to 200Hz, giving 5ms scheduler slices
  • Terminal background is drawn once; characters are not rendered twice on colored backgrounds

Adding to the kernel

  1. Add .c/.h files to kernel/ or drivers/
  2. Add the .c file to the object list in the Makefile
  3. Run make

New CupidC programs go in bin/ and are automatically embedded in RamFS at build time. New assembly demos go in demos/. CupidScript files use the .cup extension and can be placed anywhere on the VFS.


Requirements

  • NASM
  • GCC with 32-bit support (gcc-multilib on 64-bit hosts)
  • GNU Make
  • QEMU (qemu-system-i386)
  • mtools (mcopy, mdir) for FAT16 image work
  • Linux or similar Unix environment

License

GNU General Public License v3.0

Built in dedication to Terry A. Davis and TempleOS.

Releases

No releases published

Packages

 
 
 

Contributors

Languages