Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6d512b0f2 | ||
|
|
0b7a134282 | ||
|
|
91b67bd8d5 | ||
|
|
e60f232812 | ||
|
|
3169ec51cb | ||
|
|
beb2c724ff | ||
|
|
bf3c2cb578 | ||
|
|
823e9c0ce7 | ||
|
|
0ddb1e7610 | ||
|
|
32a6bb4d72 | ||
|
|
d8e680604c | ||
|
|
2e28f860cb | ||
|
|
9634ebb086 | ||
|
|
d7d97b5a97 | ||
|
|
4a3752583c | ||
|
|
9de8ee143c | ||
|
|
8d5fa53d3e | ||
|
|
ad8db32305 | ||
|
|
92928e55fb | ||
|
|
31eb7afdc6 | ||
|
|
ad9fac3e28 | ||
|
|
70cd296d19 | ||
|
|
b7020152c1 | ||
|
|
63749b8734 | ||
|
|
4e8ea5acd2 | ||
|
|
5c199e028a | ||
|
|
ec2a9d1883 | ||
|
|
4c46650c64 | ||
|
|
1ee2fcad9e | ||
|
|
5c29ac1473 | ||
|
|
81743261bf | ||
|
|
4eeb907342 | ||
|
|
e527f63af7 | ||
|
|
1e19963a8d | ||
|
|
60ab70a49d | ||
|
|
d9bcc4aff7 | ||
|
|
5604866882 | ||
|
|
e95c82b162 | ||
|
|
9fb307e603 | ||
|
|
a7c3cccce7 | ||
|
|
7eb55f3a59 | ||
|
|
72baf6506d | ||
|
|
2817ad51da | ||
|
|
5b10127e02 | ||
|
|
1404a6ae4f | ||
|
|
7b7f134e27 | ||
|
|
0491c4ad0f | ||
|
|
c6fe9971d8 | ||
|
|
88f178e368 | ||
|
|
d824b4610a | ||
|
|
a4f16b0604 | ||
|
|
83413fdd2b | ||
|
|
2a918bc7ba | ||
|
|
2624b4f8df | ||
|
|
be67c27f58 | ||
|
|
65f362feab | ||
|
|
6b18d44fab | ||
|
|
8b172a69a1 | ||
|
|
0846ed27b2 | ||
|
|
1cb8425653 | ||
|
|
f403816acf | ||
|
|
5af6b8ec5c | ||
|
|
cea0b59c93 | ||
|
|
c5111cdcb5 | ||
|
|
803ebdaefa | ||
|
|
884af3857f | ||
|
|
b427b1d4ac | ||
|
|
d01c309166 | ||
|
|
fc83d7941b | ||
|
|
3da1496e4f | ||
|
|
90e5125913 | ||
|
|
30f1b66b05 | ||
|
|
6c273e0f2f | ||
|
|
4bab8949e7 | ||
|
|
df73f00efd | ||
|
|
b05b221c41 | ||
|
|
95c465ca39 | ||
|
|
569adabf10 |
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
8
.gitignore
vendored
@@ -20,13 +20,13 @@ limine 2/limine.dSYM/Contents/Resources/DWARF/limine
|
||||
limine 2/limine.exe
|
||||
boredos.dump
|
||||
qemu-debug.log
|
||||
build/
|
||||
iso_root/
|
||||
limine/
|
||||
src/kernel/userland/bin/
|
||||
src/userland/bin/
|
||||
boredos.iso
|
||||
disk.img
|
||||
limine
|
||||
**/.DS_Store
|
||||
.DS_Store
|
||||
src/.DS_Store
|
||||
limine
|
||||
/build/
|
||||
*.o
|
||||
8
LICENSE
@@ -1,7 +1,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright(C) Chris(boreddevnl) 2024-2026
|
||||
Copyright(C) Chris (boreddevnl) 2024-2026
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
@@ -647,7 +647,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/\>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -666,11 +666,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/\>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html\>.
|
||||
|
||||
164
Makefile
@@ -10,27 +10,42 @@ LD = x86_64-elf-ld
|
||||
NASM = nasm
|
||||
XORRISO = xorriso
|
||||
|
||||
SRC_DIR = src/kernel
|
||||
SRC_DIR = src
|
||||
BUILD_DIR = build
|
||||
ISO_DIR = iso_root
|
||||
|
||||
KERNEL_ELF = $(BUILD_DIR)/boredos.elf
|
||||
ISO_IMAGE = boredos.iso
|
||||
|
||||
C_SOURCES = $(wildcard $(SRC_DIR)/*.c) \
|
||||
$(wildcard $(SRC_DIR)/lwip/core/*.c) \
|
||||
$(wildcard $(SRC_DIR)/lwip/core/ipv4/*.c) \
|
||||
$(SRC_DIR)/lwip/netif/ethernet.c \
|
||||
$(SRC_DIR)/lwip/netif/bridgeif.c
|
||||
C_SOURCES = $(wildcard $(SRC_DIR)/core/*.c) \
|
||||
$(wildcard $(SRC_DIR)/sys/*.c) \
|
||||
$(wildcard $(SRC_DIR)/mem/*.c) \
|
||||
$(wildcard $(SRC_DIR)/dev/*.c) \
|
||||
$(wildcard $(SRC_DIR)/net/*.c) \
|
||||
$(wildcard $(SRC_DIR)/net/nic/*.c) \
|
||||
$(wildcard $(SRC_DIR)/fs/*.c) \
|
||||
$(wildcard $(SRC_DIR)/wm/*.c) \
|
||||
$(wildcard $(SRC_DIR)/net/lwip/core/*.c) \
|
||||
$(wildcard $(SRC_DIR)/net/lwip/core/ipv4/*.c) \
|
||||
$(SRC_DIR)/net/lwip/netif/ethernet.c \
|
||||
$(SRC_DIR)/net/lwip/netif/bridgeif.c
|
||||
|
||||
ASM_SOURCES = $(wildcard $(SRC_DIR)/*.asm)
|
||||
OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(C_SOURCES)) \
|
||||
$(patsubst $(SRC_DIR)/%.asm, $(BUILD_DIR)/%.o, $(ASM_SOURCES))
|
||||
ASM_SOURCES = $(wildcard $(SRC_DIR)/arch/*.asm)
|
||||
OBJ_FILES = $(patsubst $(SRC_DIR)/core/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/core/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/sys/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/sys/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/mem/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/mem/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/dev/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/dev/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/net/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/net/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/net/nic/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/net/nic/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/fs/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/fs/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/wm/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/wm/*.c)) \
|
||||
$(patsubst $(SRC_DIR)/net/lwip/%.c, $(BUILD_DIR)/lwip/%.o, $(filter $(SRC_DIR)/net/lwip/%.c, $(C_SOURCES))) \
|
||||
$(patsubst $(SRC_DIR)/arch/%.asm, $(BUILD_DIR)/%.o, $(ASM_SOURCES))
|
||||
|
||||
CFLAGS = -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding \
|
||||
-fno-stack-protector -fno-stack-check -fno-lto -fPIE \
|
||||
-m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone \
|
||||
-I$(SRC_DIR) -I$(SRC_DIR)/lwip
|
||||
-I$(SRC_DIR) -I$(SRC_DIR)/net/lwip -I$(SRC_DIR)/core -I$(SRC_DIR)/sys -I$(SRC_DIR)/mem -I$(SRC_DIR)/dev -I$(SRC_DIR)/net -I$(SRC_DIR)/net/nic -I$(SRC_DIR)/fs -I$(SRC_DIR)/wm
|
||||
|
||||
LDFLAGS = -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker \
|
||||
-z text -z max-page-size=0x1000 -T linker.ld
|
||||
@@ -54,9 +69,9 @@ limine-setup:
|
||||
rm -rf limine; \
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=v$(LIMINE_VERSION)-binary --depth=1 limine; \
|
||||
fi
|
||||
@if [ ! -f $(SRC_DIR)/limine.h ]; then \
|
||||
@if [ ! -f $(SRC_DIR)/core/limine.h ]; then \
|
||||
echo "Copying limine.h..."; \
|
||||
cp limine/limine.h $(SRC_DIR)/limine.h; \
|
||||
cp limine/limine.h $(SRC_DIR)/core/limine.h; \
|
||||
fi
|
||||
@echo "Building Limine host utility..."; \
|
||||
$(MAKE) -C limine
|
||||
@@ -65,66 +80,108 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/core/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/sys/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.asm | $(BUILD_DIR)
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/mem/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/dev/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/net/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/net/nic/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/fs/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/wm/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/lwip/%.o: $(SRC_DIR)/net/lwip/%.c | $(BUILD_DIR) limine-setup
|
||||
mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/arch/%.asm | $(BUILD_DIR)
|
||||
$(NASM) $(NASMFLAGS) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/test_syscall.o: $(SRC_DIR)/test_syscall.asm | $(BUILD_DIR)
|
||||
$(BUILD_DIR)/test_syscall.o: $(SRC_DIR)/arch/test_syscall.asm | $(BUILD_DIR)
|
||||
$(NASM) $(NASMFLAGS) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/user_test.o: $(SRC_DIR)/user_test.asm | $(BUILD_DIR)
|
||||
$(BUILD_DIR)/user_test.o: $(SRC_DIR)/arch/user_test.asm | $(BUILD_DIR)
|
||||
$(NASM) $(NASMFLAGS) $< -o $@
|
||||
|
||||
$(BUILD_DIR)/process_asm.o: $(SRC_DIR)/process_asm.asm | $(BUILD_DIR)
|
||||
$(BUILD_DIR)/process_asm.o: $(SRC_DIR)/arch/process_asm.asm | $(BUILD_DIR)
|
||||
$(NASM) $(NASMFLAGS) $< -o $@
|
||||
|
||||
$(KERNEL_ELF): $(OBJ_FILES)
|
||||
$(LD) $(LDFLAGS) -o $@ $(OBJ_FILES)
|
||||
$(MAKE) -C $(SRC_DIR)/userland
|
||||
|
||||
$(ISO_IMAGE): $(KERNEL_ELF) limine.conf limine-setup
|
||||
$(BUILD_DIR)/initrd.tar: $(KERNEL_ELF)
|
||||
rm -rf $(BUILD_DIR)/initrd
|
||||
mkdir -p $(BUILD_DIR)/initrd/bin
|
||||
mkdir -p $(BUILD_DIR)/initrd/Library/images/Wallpapers
|
||||
mkdir -p $(BUILD_DIR)/initrd/Library/images/gif
|
||||
mkdir -p $(BUILD_DIR)/initrd/Library/Fonts/Emoji
|
||||
mkdir -p $(BUILD_DIR)/initrd/Library/DOOM
|
||||
mkdir -p $(BUILD_DIR)/initrd/docs
|
||||
|
||||
@for f in $(SRC_DIR)/userland/bin/*.elf; do \
|
||||
if [ -f "$$f" ]; then cp "$$f" $(BUILD_DIR)/initrd/bin/; fi \
|
||||
done
|
||||
@for f in $(SRC_DIR)/images/wallpapers/*; do \
|
||||
if [ -f "$$f" ]; then cp "$$f" $(BUILD_DIR)/initrd/Library/images/Wallpapers/; fi \
|
||||
done
|
||||
@for f in $(SRC_DIR)/images/gif/*.gif; do \
|
||||
if [ -f "$$f" ]; then cp "$$f" $(BUILD_DIR)/initrd/Library/images/gif/; fi \
|
||||
done
|
||||
@for f in $(SRC_DIR)/fonts/*.ttf; do \
|
||||
if [ -f "$$f" ]; then cp "$$f" $(BUILD_DIR)/initrd/Library/Fonts/; fi \
|
||||
done
|
||||
@for f in $(SRC_DIR)/fonts/Emoji/*.ttf; do \
|
||||
if [ -f "$$f" ]; then cp "$$f" $(BUILD_DIR)/initrd/Library/Fonts/Emoji/; fi \
|
||||
done
|
||||
@if [ -f $(SRC_DIR)/userland/games/doom/doom1.wad ]; then cp $(SRC_DIR)/userland/games/doom/doom1.wad $(BUILD_DIR)/initrd/Library/DOOM/; fi
|
||||
@for f in $$(find docs -name '*.md' 2>/dev/null); do \
|
||||
if [ -f "$$f" ]; then \
|
||||
dir=$$(dirname "$$f"); \
|
||||
mkdir -p $(BUILD_DIR)/initrd/"$$dir"; \
|
||||
cp "$$f" $(BUILD_DIR)/initrd/"$$dir"/; \
|
||||
fi \
|
||||
done
|
||||
@if [ -f README.md ]; then cp README.md $(BUILD_DIR)/initrd/; fi
|
||||
@if [ -f LICENSE ]; then cp LICENSE $(BUILD_DIR)/initrd/; fi
|
||||
|
||||
cd $(BUILD_DIR)/initrd && COPYFILE_DISABLE=1 tar --exclude="._*" -cf ../initrd.tar *
|
||||
|
||||
$(ISO_IMAGE): $(KERNEL_ELF) $(BUILD_DIR)/initrd.tar limine.conf limine-setup
|
||||
rm -rf $(ISO_DIR)
|
||||
mkdir -p $(ISO_DIR)
|
||||
mkdir -p $(ISO_DIR)/EFI/BOOT
|
||||
|
||||
cp $(KERNEL_ELF) $(ISO_DIR)/
|
||||
cp limine.conf $(ISO_DIR)/
|
||||
mkdir -p $(ISO_DIR)/bin
|
||||
@for f in $(SRC_DIR)/userland/bin/*.elf; do \
|
||||
if [ -f "$$f" ]; then \
|
||||
basename=$$(basename "$$f"); \
|
||||
cp "$$f" $(ISO_DIR)/bin/; \
|
||||
echo " module_path: boot():/bin/$$basename" >> $(ISO_DIR)/limine.conf; \
|
||||
fi \
|
||||
done
|
||||
|
||||
@if [ -f README.md ]; then cp README.md $(ISO_DIR)/; fi
|
||||
@if [ -f $(SRC_DIR)/userland/doom/doom1.wad ]; then \
|
||||
mkdir -p $(ISO_DIR)/Library/DOOM; \
|
||||
cp $(SRC_DIR)/userland/doom/doom1.wad $(ISO_DIR)/Library/DOOM/; \
|
||||
echo " module_path: boot():/Library/DOOM/doom1.wad" >> $(ISO_DIR)/limine.conf; \
|
||||
fi
|
||||
cp $(BUILD_DIR)/initrd.tar $(ISO_DIR)/
|
||||
echo " module_path: boot():/initrd.tar" >> $(ISO_DIR)/limine.conf
|
||||
|
||||
mkdir -p $(ISO_DIR)/Library/images/Wallpapers
|
||||
@for f in $(SRC_DIR)/images/wallpapers/*; do \
|
||||
if [ -f "$$f" ]; then \
|
||||
basename=$$(basename "$$f"); \
|
||||
cp "$$f" $(ISO_DIR)/Library/images/Wallpapers/; \
|
||||
echo " module_path: boot():/Library/images/Wallpapers/$$basename" >> $(ISO_DIR)/limine.conf; \
|
||||
fi \
|
||||
done
|
||||
@if [ -f splash.jpg ]; then cp splash.jpg $(ISO_DIR)/; fi
|
||||
|
||||
mkdir -p $(ISO_DIR)/Library/images/gif
|
||||
@for f in $(SRC_DIR)/images/gif/*.gif; do \
|
||||
if [ -f "$$f" ]; then \
|
||||
basename=$$(basename "$$f"); \
|
||||
cp "$$f" $(ISO_DIR)/Library/images/gif/; \
|
||||
echo " module_path: boot():/Library/images/gif/$$basename" >> $(ISO_DIR)/limine.conf; \
|
||||
fi \
|
||||
done
|
||||
|
||||
cp limine/limine-bios.sys $(ISO_DIR)/
|
||||
cp limine/limine-bios-cd.bin $(ISO_DIR)/
|
||||
cp limine/limine-uefi-cd.bin $(ISO_DIR)/
|
||||
@@ -132,15 +189,6 @@ $(ISO_IMAGE): $(KERNEL_ELF) limine.conf limine-setup
|
||||
cp limine/BOOTX64.EFI $(ISO_DIR)/EFI/BOOT/
|
||||
cp limine/BOOTIA32.EFI $(ISO_DIR)/EFI/BOOT/
|
||||
|
||||
mkdir -p $(ISO_DIR)/Library/Fonts
|
||||
@for f in $(SRC_DIR)/fonts/*.ttf; do \
|
||||
if [ -f "$$f" ]; then \
|
||||
basename=$$(basename "$$f"); \
|
||||
cp "$$f" $(ISO_DIR)/Library/Fonts/; \
|
||||
echo " module_path: boot():/Library/Fonts/$$basename" >> $(ISO_DIR)/limine.conf; \
|
||||
fi \
|
||||
done
|
||||
|
||||
$(XORRISO) -as mkisofs -R -J -b limine-bios-cd.bin \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
--efi-boot limine-uefi-cd.bin \
|
||||
@@ -157,7 +205,7 @@ run: $(ISO_IMAGE)
|
||||
qemu-system-x86_64 -m 4G -serial stdio -cdrom $< -boot d \
|
||||
-smp 4 \
|
||||
-audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0 \
|
||||
-netdev user,id=net0,hostfwd=udp::12346-:12345 -device e1000,netdev=net0 \
|
||||
-netdev user,id=net0,hostfwd=udp::12346-:12345 -device virtio-net-pci,netdev=net0 \
|
||||
-vga std -global VGA.xres=1920 -global VGA.yres=1080 \
|
||||
-display cocoa,show-cursor=off \
|
||||
-drive file=disk.img,format=raw,file.locking=off \
|
||||
|
||||
191
README.md
@@ -2,167 +2,86 @@
|
||||
|
||||
<div align="center">
|
||||
<img src="boredos.svg" alt="BoredOS Logo" width="450" />
|
||||
<p><em>A modern x86_64 hobbyist operating system built from the ground up.</em></p>
|
||||
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||

|
||||

|
||||
</div>
|
||||
BoredOS is a simple x86_64 hobbyist operating system.
|
||||
It features a DE (and WM), a FAT32 filesystem, customizable UI and much much more!
|
||||
|
||||
---
|
||||
|
||||
BoredOS is a x86_64 operating system featuring a custom Desktop Environment (DE), a dedicated Window Manager (BoredWM), and a FAT32 filesystem. It balances low-level kernel exploration with a surprisingly capable userspace.
|
||||
|
||||

|
||||
*this screenshot might be outdated*
|
||||
> [!NOTE]
|
||||
> *The screenshot above may represent a previous build and is subject to change as the UI evolves.*
|
||||
|
||||
## Features
|
||||
- userspace
|
||||
- JPG image support
|
||||
- Disk manager
|
||||
- Drag and drop mouse centered UI
|
||||
- Customizable UI
|
||||
- Basic Networking Stack
|
||||
- Bored WM
|
||||
- FAT32 filesystem
|
||||
- 64-bit long mode support
|
||||
- Multiboot2 compliant
|
||||
- Text editor
|
||||
- Markdown Viewer
|
||||
- Minesweeper
|
||||
- Markdown Viewer
|
||||
- GUI Text editor
|
||||
- Paint application
|
||||
- IDT
|
||||
- Ability to run on actual x86_64 hardware
|
||||
- CLI
|
||||
- (Limited) C Compiler
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
## 🚀 Features
|
||||
|
||||
To build BoredOS, you'll need the following tools installed:
|
||||
### ⚙️ System Architecture
|
||||
* **64-bit Long Mode:** Fully utilizing the x86_64 architecture.
|
||||
* **Symmetric Multi-Processing (SMP):** Full support for multi-core CPUs via Limine SMP.
|
||||
* **LAPIC & IPI Scheduling:** Advanced interrupt handling and inter-processor communication for task distribution.
|
||||
* **SMP-Safe Spinlocks:** Robust kernel-wide synchronization for VFS, process management, and the GUI.
|
||||
* **Multiboot2 Compliant:** Bootable on real hardware and modern emulators.
|
||||
* **Kernel Core:** Interrupt Descriptor Table (IDT) management and a robust syscall interface.
|
||||
* **Filesystem:** Full **FAT32** support for persistent and in-memory storage.
|
||||
* **Networking:** Includes the lwIP networking stack.
|
||||
|
||||
- **x86_64 ELF Toolchain**: `x86_64-elf-gcc`, `x86_64-elf-ld`
|
||||
- **NASM**: Netwide Assembler for compiling assembly code
|
||||
- **xorriso**: For creating bootable ISO images
|
||||
- **QEMU** (optional): For testing the kernel in an emulator
|
||||
### 📺 Graphical User Interface
|
||||
* **BoredWM:** A custom Window Manager with drag-and-drop, mouse-centered interaction.
|
||||
* **Customization:** Adjustable UI to suit your aesthetic.
|
||||
* **Media Support:** Built-in image decoding.
|
||||
|
||||
On macOS, you can install these using Homebrew:
|
||||
```sh
|
||||
brew install x86_64-elf-binutils x86_64-elf-gcc nasm xorriso qemu
|
||||
```
|
||||
### 🛠️ Included Applications
|
||||
* **Productivity:** GUI Text Editor calculator, Markdown Viewer, a simple browser and BoredWord.
|
||||
* **Creativity:** A Paint application.
|
||||
* **Utilities:** Terminal, Task Manager, File Explorer, Clock and a (limited) C Compiler.
|
||||
* **Games:** Minesweeper and DOOM.
|
||||
|
||||
## Building
|
||||
---
|
||||
|
||||
Simply run `make` from the project root:
|
||||
## 📚 Documentation
|
||||
|
||||
```sh
|
||||
make
|
||||
```
|
||||
Explore the internal workings of BoredOS via our comprehensive guides in the [`docs/`](docs/) directory.
|
||||
|
||||
This will:
|
||||
1. Compile all kernel C sources and assembly files
|
||||
2. Link the kernel ELF binary
|
||||
3. Generate a bootable ISO image (`boredos.iso`)
|
||||
* 📖 **[Documentation Index](docs/README.md)** – Start here.
|
||||
* 🏗️ **[Architecture Overview](docs/architecture/core.md)** – Deep dive into the kernel.
|
||||
* 🔨 **[Building and Running](docs/build/usage.md)** – Setup your build environment.
|
||||
* 🚀 **[AppDev SDK](docs/appdev/custom_apps.md)** – Build your own apps for BoredOS.
|
||||
|
||||
The build output is organized as follows:
|
||||
- Compiled object files: `build/`
|
||||
- ISO root filesystem: `iso_root/`
|
||||
- Final ISO image: `boredos.iso`
|
||||
---
|
||||
|
||||
## Running
|
||||
## ☕ Support the Journey
|
||||
|
||||
### QEMU Emulation
|
||||
If you find this project interesting or helpful, consider fueling the development with a coffee!
|
||||
|
||||
Run the kernel in QEMU:
|
||||
|
||||
```sh
|
||||
make run
|
||||
```
|
||||
|
||||
Or manually:
|
||||
```sh
|
||||
qemu-system-x86_64 -m 2G -serial stdio -cdrom boredos.iso -boot d
|
||||
```
|
||||
|
||||
### Running on Real Hardware
|
||||
|
||||
*Warning: This is at YOUR OWN RISK. This software comes with ZERO warranty and may break your system.*
|
||||
|
||||
1. **Create bootable USB**: Use [Balena Etcher](https://www.balena.io/etcher/) to flash `boredos.iso` to a USB drive
|
||||
|
||||
2. **Prepare the system**:
|
||||
- Enable legacy (BIOS) boot in your system BIOS/UEFI settings
|
||||
- Disable Secure Boot if needed
|
||||
|
||||
3. **Boot**: Insert the USB drive and select it in the boot menu during startup
|
||||
|
||||
**Networking requires an Intel E1000 network card or similar while using Ethernet.**
|
||||
|
||||
4. **Tested Hardware**:
|
||||
- HP EliteDesk 705 G4 DM (AMD Ryzen 5 PRO 2400G, Radeon Vega) **Tested, no networking.**
|
||||
- Lenovo ThinkPad A475 20KL002VMH (AMD Pro A12-8830B, Radeon R7) **Tested, no networking.**
|
||||
- Acer Aspire E5-573-311M (Intel Core i3-5005U, Intel HD Graphics) **Tested, no networking.**
|
||||
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `src/kernel/` - Main kernel implementation
|
||||
- `boot.asm` - Boot assembly code
|
||||
- `main.c` - Kernel entry point
|
||||
- `*.c / *.h` - Core kernel modules (graphics, interrupts, filesystem, etc.)
|
||||
- `cli_apps/` - Command-line applications
|
||||
- `build/` - Compiled object files (generated during build)
|
||||
- `iso_root/` - ISO filesystem layout (generated during build)
|
||||
- `limine/` - Limine bootloader files (downloaded automatically)
|
||||
- `linker.ld` - Linker script for x86_64 ELF
|
||||
- `limine.conf` - Limine bootloader configuration
|
||||
- `Makefile` - Build configuration and targets
|
||||
|
||||
|
||||
|
||||
|
||||
###
|
||||
###
|
||||
|
||||
<h2 align="left">Help me brew some coffee! ☕️</h2>
|
||||
|
||||
###
|
||||
|
||||
<p align="left">
|
||||
If you enjoy this project, and like what i'm doing here, consider buying me a coffee!
|
||||
<br><br>
|
||||
<a href="https://buymeacoffee.com/boreddevnl" target="_blank">
|
||||
<a href="https://buymeacoffee.com/boreddevnl" target="_blank">
|
||||
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50" style="border-radius: 8px;" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
###
|
||||
</a>
|
||||
|
||||
|
||||
## This project was previously labeled as "BrewKernel"
|
||||
Brewkernel was a text only very simple (and messy) project i started 3 years ago. It was my first work in OSDev and i absolutely loved it. It sadly just got too messy and i myself couldn't understand my own code anymore. About a year ago i started work on BoredOS, and pushed a *"working"* version of it a few days ago as of writing this *(Feb. 10 2026)*
|
||||
Brewkernel has already been deprecated and will not be accepting any pull requests or fix any issues as it is now a public archive.
|
||||
Thanks to everyone who helped me with Brewkernel, even if it were just ideas, and intend to keep working on this for the forseeable future!
|
||||
---
|
||||
|
||||
## License
|
||||
## ⚠️ Project Disclaimer & Heritage
|
||||
|
||||
Copyright (C) 2024-2026 boreddevnl
|
||||
**BoredOS** is the successor to **BrewKernel**, a text-only project initiated in 2023.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
While BrewKernel served as the foundational learning ground for this OS, it has been officially **deprecated and archived**. It no longer receives updates, bug fixes, or pull request reviews. BoredOS represents a complete architectural reboot, applying years of lessons learned to create a cleaner, more modular, and more capable 64-bit system.
|
||||
|
||||
NOTICE
|
||||
------
|
||||
> [!IMPORTANT]
|
||||
> Please ensure all issues, discussions, and contributions are directed to this repository. Legacy BrewKernel code is preserved for historical purposes only and is not compatible with BoredOS.
|
||||
|
||||
This product includes software developed by Chris ("boreddevnl") as part of the BoredOS (Previously Brewkernel/BrewOS) project.
|
||||
---
|
||||
|
||||
Copyright (C) 2024–2026 Chris / boreddevnl (previously boreddevhq)
|
||||
## ⚖️ License
|
||||
|
||||
All source files in this repository contain copyright and license
|
||||
headers that must be preserved in redistributions and derivative works.
|
||||
**Copyright (C) 2024-2026 boreddevnl**
|
||||
|
||||
If you distribute or modify this project (in whole or in part),
|
||||
you MUST:
|
||||
Distributed under the **GNU General Public License v3**. See the `LICENSE` file for details.
|
||||
|
||||
- Retain all copyright and license headers at the top of each file.
|
||||
- Include this NOTICE file along with any redistributions or
|
||||
derivative works.
|
||||
- Provide clear attribution to the original author in documentation
|
||||
or credits where appropriate.
|
||||
|
||||
The above attribution requirements are informational and intended to
|
||||
ensure proper credit is given. They do not alter or supersede the
|
||||
terms of the GNU General Public License (GPL), which governs this work.
|
||||
> [!IMPORTANT]
|
||||
> This product includes software developed by Chris ("boreddevnl"). You must retain all copyright headers and include the original attribution in any redistributions or derivative works. See the `NOTICE` file for more details.
|
||||
BIN
boredos.iso
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 130" width="100%">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 415 130" width="100%">
|
||||
<style>
|
||||
text {
|
||||
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
533
build.log
@@ -1,533 +0,0 @@
|
||||
mkdir -p build
|
||||
mkdir -p build
|
||||
Building Limine host utility...
|
||||
make[1]: Nothing to be done for `all'.
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/cmd.c -o build/cmd.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/disk_manager.c -o build/disk_manager.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/e1000.c -o build/e1000.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/e1000_netif.c -o build/e1000_netif.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/elf.c -o build/elf.o
|
||||
src/kernel/elf.c:12:13: warning: 'print_hex' defined but not used [-Wunused-function]
|
||||
12 | static void print_hex(uint64_t n) {
|
||||
| ^~~~~~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/explorer.c -o build/explorer.o
|
||||
src/kernel/explorer.c: In function 'explorer_draw_file_icon':
|
||||
src/kernel/explorer.c:887:73: warning: unused parameter 'color' [-Wunused-parameter]
|
||||
887 | static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, const char *filename, const char *current_path) {
|
||||
| ~~~~~~~~~^~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/fat32.c -o build/fat32.o
|
||||
src/kernel/fat32.c: In function 'fat32_normalize_path':
|
||||
src/kernel/fat32.c:151:10: warning: unused variable 'drive' [-Wunused-variable]
|
||||
151 | char drive = parse_drive_from_path(&p);
|
||||
| ^~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/font_manager.c -o build/font_manager.o
|
||||
In file included from src/kernel/font_manager.c:4:
|
||||
src/kernel/stb_truetype.h: In function 'stbtt_FreeShape':
|
||||
src/kernel/stb_truetype.h:2672:54: warning: unused parameter 'info' [-Wunused-parameter]
|
||||
2672 | STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~^~~~
|
||||
src/kernel/stb_truetype.h: In function 'stbtt__hheap_alloc':
|
||||
src/kernel/stb_truetype.h:2770:70: warning: unused parameter 'userdata' [-Wunused-parameter]
|
||||
2770 | static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
|
||||
| ~~~~~~^~~~~~~~
|
||||
src/kernel/stb_truetype.h: In function 'stbtt__hheap_cleanup':
|
||||
src/kernel/stb_truetype.h:2797:58: warning: unused parameter 'userdata' [-Wunused-parameter]
|
||||
2797 | static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
|
||||
| ~~~~~~^~~~~~~~
|
||||
src/kernel/stb_truetype.h: In function 'stbtt_FlattenCurves':
|
||||
src/kernel/stb_truetype.h:3618:154: warning: unused parameter 'userdata' [-Wunused-parameter]
|
||||
3618 | static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
|
||||
| ~~~~~~^~~~~~~~
|
||||
src/kernel/stb_truetype.h: In function 'stbtt_FreeBitmap':
|
||||
src/kernel/stb_truetype.h:3708:62: warning: unused parameter 'userdata' [-Wunused-parameter]
|
||||
3708 | STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
|
||||
| ~~~~~~^~~~~~~~
|
||||
src/kernel/stb_truetype.h: In function 'stbtt_FreeSDF':
|
||||
src/kernel/stb_truetype.h:4767:59: warning: unused parameter 'userdata' [-Wunused-parameter]
|
||||
4767 | STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
|
||||
| ~~~~~~^~~~~~~~
|
||||
src/kernel/font_manager.c: In function 'font_manager_load':
|
||||
src/kernel/font_manager.c:93:9: warning: unused variable 'read' [-Wunused-variable]
|
||||
93 | int read = fat32_read(fh, buffer, fsize);
|
||||
| ^~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/gdt.c -o build/gdt.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/graphics.c -o build/graphics.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/idt.c -o build/idt.o
|
||||
src/kernel/idt.c: In function 'pic_remap':
|
||||
src/kernel/idt.c:110:17: warning: variable 'a2' set but not used [-Wunused-but-set-variable]
|
||||
110 | uint8_t a1, a2;
|
||||
| ^~
|
||||
src/kernel/idt.c:110:13: warning: variable 'a1' set but not used [-Wunused-but-set-variable]
|
||||
110 | uint8_t a1, a2;
|
||||
| ^~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/kutils.c -o build/kutils.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/licensewr.c -o build/licensewr.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip_port.c -o build/lwip_port.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/main.c -o build/main.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/memory_manager.c -o build/memory_manager.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/nanojpeg.c -o build/nanojpeg.o
|
||||
src/kernel/nanojpeg.c: In function 'njGetVLC':
|
||||
src/kernel/nanojpeg.c:686:24: warning: left shift of negative value [-Wshift-negative-value]
|
||||
686 | value += ((-1) << bits) + 1;
|
||||
| ^~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/network.c -o build/network.o
|
||||
src/kernel/network.c: In function 'network_dhcp_acquire':
|
||||
src/kernel/network.c:181:9: warning: unused variable 'loops' [-Wunused-variable]
|
||||
181 | int loops = 0;
|
||||
| ^~~~~
|
||||
src/kernel/network.c: In function 'network_init':
|
||||
src/kernel/network.c:97:9: warning: 'ip.bytes[0]' may be used uninitialized [-Wmaybe-uninitialized]
|
||||
97 | k_itoa(ip.bytes[0], buf); serial_write(buf); serial_write(".");
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/network.c:92:24: note: 'ip.bytes[0]' was declared here
|
||||
92 | ipv4_address_t ip;
|
||||
| ^~
|
||||
src/kernel/network.c:98:9: warning: 'ip.bytes[1]' may be used uninitialized [-Wmaybe-uninitialized]
|
||||
98 | k_itoa(ip.bytes[1], buf); serial_write(buf); serial_write(".");
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/network.c:92:24: note: 'ip.bytes[1]' was declared here
|
||||
92 | ipv4_address_t ip;
|
||||
| ^~
|
||||
src/kernel/network.c:99:9: warning: 'ip.bytes[2]' may be used uninitialized [-Wmaybe-uninitialized]
|
||||
99 | k_itoa(ip.bytes[2], buf); serial_write(buf); serial_write(".");
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/network.c:92:24: note: 'ip.bytes[2]' was declared here
|
||||
92 | ipv4_address_t ip;
|
||||
| ^~
|
||||
src/kernel/network.c:100:9: warning: 'ip.bytes[3]' may be used uninitialized [-Wmaybe-uninitialized]
|
||||
100 | k_itoa(ip.bytes[3], buf); serial_write(buf); serial_write("\n");
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/network.c:92:24: note: 'ip.bytes[3]' was declared here
|
||||
92 | ipv4_address_t ip;
|
||||
| ^~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/nj_kernel.c -o build/nj_kernel.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/paging.c -o build/paging.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/panic.c -o build/panic.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/pci.c -o build/pci.o
|
||||
src/kernel/pci.c: In function 'pci_enumerate_devices':
|
||||
src/kernel/pci.c:52:31: warning: comparison is always true due to limited range of data type [-Wtype-limits]
|
||||
52 | for (uint8_t bus = 0; bus < 256 && count < max_devices; bus++) {
|
||||
| ^
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/platform.c -o build/platform.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/process.c -o build/process.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/ps2.c -o build/ps2.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/rtc.c -o build/rtc.o
|
||||
src/kernel/rtc.c: In function 'rtc_get_datetime':
|
||||
src/kernel/rtc.c:28:13: warning: unused variable 'last_century' [-Wunused-variable]
|
||||
28 | uint8_t last_century;
|
||||
| ^~~~~~~~~~~~
|
||||
src/kernel/rtc.c:21:13: warning: unused variable 'century' [-Wunused-variable]
|
||||
21 | uint8_t century;
|
||||
| ^~~~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/syscall.c -o build/syscall.o
|
||||
src/kernel/syscall.c: In function 'syscall_handler_inner':
|
||||
src/kernel/syscall.c:399:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
399 | float scale = *(float*)&scale_bits;
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/syscall.c:509:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
509 | float scale = *(float*)&scale_bits;
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
src/kernel/syscall.c:528:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
528 | float scale = *(float*)&scale_bits;
|
||||
| ^~~~~~~~~~~~~~~~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/vm.c -o build/vm.o
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/wallpaper.c -o build/wallpaper.o
|
||||
src/kernel/wallpaper.c:83:13: warning: 'serial_num' defined but not used [-Wunused-function]
|
||||
83 | static void serial_num(int n) {
|
||||
| ^~~~~~~~~~
|
||||
mkdir -p build/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/wm.c -o build/wm.o
|
||||
src/kernel/wm.c: In function 'wm_handle_click':
|
||||
src/kernel/wm.c:1570:29: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
|
||||
1570 | if (col < 0) col = 0; if (row < 0) row = 0;
|
||||
| ^~
|
||||
src/kernel/wm.c:1570:51: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
|
||||
1570 | if (col < 0) col = 0; if (row < 0) row = 0;
|
||||
| ^~
|
||||
src/kernel/wm.c: In function 'wm_handle_mouse':
|
||||
src/kernel/wm.c:2214:41: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
|
||||
2214 | if (col < 0) col = 0; if (row < 0) row = 0;
|
||||
| ^~
|
||||
src/kernel/wm.c:2214:63: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
|
||||
2214 | if (col < 0) col = 0; if (row < 0) row = 0;
|
||||
| ^~
|
||||
src/kernel/wm.c: At top level:
|
||||
src/kernel/wm.c:1124:13: warning: 'erase_cursor' defined but not used [-Wunused-function]
|
||||
1124 | static void erase_cursor(int x, int y) {
|
||||
| ^~~~~~~~~~~~
|
||||
src/kernel/wm.c:1014:13: warning: 'draw_dock_editor' defined but not used [-Wunused-function]
|
||||
1014 | static void draw_dock_editor(int x, int y) {
|
||||
| ^~~~~~~~~~~~~~~~
|
||||
src/kernel/wm.c:87:13: warning: 'cursor_visible' defined but not used [-Wunused-variable]
|
||||
87 | static bool cursor_visible = true;
|
||||
| ^~~~~~~~~~~~~~
|
||||
src/kernel/wm.c:84:12: warning: 'desktop_refresh_timer' defined but not used [-Wunused-variable]
|
||||
84 | static int desktop_refresh_timer = 0;
|
||||
| ^~~~~~~~~~~~~~~~~~~~~
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/altcp.c -o build/lwip/core/altcp.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/altcp_alloc.c -o build/lwip/core/altcp_alloc.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/altcp_tcp.c -o build/lwip/core/altcp_tcp.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/def.c -o build/lwip/core/def.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/dns.c -o build/lwip/core/dns.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/inet_chksum.c -o build/lwip/core/inet_chksum.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/init.c -o build/lwip/core/init.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ip.c -o build/lwip/core/ip.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/mem.c -o build/lwip/core/mem.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/memp.c -o build/lwip/core/memp.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/netif.c -o build/lwip/core/netif.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/pbuf.c -o build/lwip/core/pbuf.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/raw.c -o build/lwip/core/raw.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/stats.c -o build/lwip/core/stats.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/sys.c -o build/lwip/core/sys.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/tcp.c -o build/lwip/core/tcp.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/tcp_in.c -o build/lwip/core/tcp_in.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/tcp_out.c -o build/lwip/core/tcp_out.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/timeouts.c -o build/lwip/core/timeouts.o
|
||||
mkdir -p build/lwip/core/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/udp.c -o build/lwip/core/udp.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/autoip.c -o build/lwip/core/ipv4/autoip.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/dhcp.c -o build/lwip/core/ipv4/dhcp.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/etharp.c -o build/lwip/core/ipv4/etharp.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/icmp.c -o build/lwip/core/ipv4/icmp.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/igmp.c -o build/lwip/core/ipv4/igmp.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/ip4.c -o build/lwip/core/ipv4/ip4.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/ip4_addr.c -o build/lwip/core/ipv4/ip4_addr.o
|
||||
mkdir -p build/lwip/core/ipv4/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/core/ipv4/ip4_frag.c -o build/lwip/core/ipv4/ip4_frag.o
|
||||
mkdir -p build/lwip/netif/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/netif/ethernet.c -o build/lwip/netif/ethernet.o
|
||||
mkdir -p build/lwip/netif/
|
||||
x86_64-elf-gcc -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -msse -msse2 -mstackrealign -mno-red-zone -Isrc/kernel -Isrc/kernel/lwip -c src/kernel/lwip/netif/bridgeif.c -o build/lwip/netif/bridgeif.o
|
||||
nasm -f elf64 src/kernel/boot.asm -o build/boot.o
|
||||
nasm -f elf64 src/kernel/gdt_asm.asm -o build/gdt_asm.o
|
||||
nasm -f elf64 src/kernel/interrupts.asm -o build/interrupts.o
|
||||
nasm -f elf64 src/kernel/process_asm.asm -o build/process_asm.o
|
||||
nasm -f elf64 src/kernel/syscalls.asm -o build/syscalls.o
|
||||
nasm -f elf64 src/kernel/test_syscall.asm -o build/test_syscall.o
|
||||
nasm -f elf64 src/kernel/user_test.asm -o build/user_test.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker -z text -z max-page-size=0x1000 -T linker.ld -o build/boredos.elf build/cmd.o build/disk_manager.o build/e1000.o build/e1000_netif.o build/elf.o build/explorer.o build/fat32.o build/font_manager.o build/gdt.o build/graphics.o build/idt.o build/kutils.o build/licensewr.o build/lwip_port.o build/main.o build/memory_manager.o build/nanojpeg.o build/network.o build/nj_kernel.o build/paging.o build/panic.o build/pci.o build/platform.o build/process.o build/ps2.o build/rtc.o build/syscall.o build/vm.o build/wallpaper.o build/wm.o build/lwip/core/altcp.o build/lwip/core/altcp_alloc.o build/lwip/core/altcp_tcp.o build/lwip/core/def.o build/lwip/core/dns.o build/lwip/core/inet_chksum.o build/lwip/core/init.o build/lwip/core/ip.o build/lwip/core/mem.o build/lwip/core/memp.o build/lwip/core/netif.o build/lwip/core/pbuf.o build/lwip/core/raw.o build/lwip/core/stats.o build/lwip/core/sys.o build/lwip/core/tcp.o build/lwip/core/tcp_in.o build/lwip/core/tcp_out.o build/lwip/core/timeouts.o build/lwip/core/udp.o build/lwip/core/ipv4/autoip.o build/lwip/core/ipv4/dhcp.o build/lwip/core/ipv4/etharp.o build/lwip/core/ipv4/icmp.o build/lwip/core/ipv4/igmp.o build/lwip/core/ipv4/ip4.o build/lwip/core/ipv4/ip4_addr.o build/lwip/core/ipv4/ip4_frag.o build/lwip/netif/ethernet.o build/lwip/netif/bridgeif.o build/boot.o build/gdt_asm.o build/interrupts.o build/process_asm.o build/syscalls.o build/test_syscall.o build/user_test.o
|
||||
x86_64-elf-ld: warning: build/boredos.elf has a LOAD segment with RWX permissions
|
||||
/Library/Developer/CommandLineTools/usr/bin/make -C src/kernel/userland
|
||||
mkdir -p bin
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c libc/libui.c -o bin/libui.o
|
||||
libc/libui.c: In function 'ui_draw_string_scaled':
|
||||
libc/libui.c:64:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
64 | uint32_t scale_bits = *(uint32_t*)&scale;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
libc/libui.c: In function 'ui_get_string_width_scaled':
|
||||
libc/libui.c:70:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
70 | uint32_t scale_bits = *(uint32_t*)&scale;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
libc/libui.c: In function 'ui_get_font_height_scaled':
|
||||
libc/libui.c:75:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
|
||||
75 | uint32_t scale_bits = *(uint32_t*)&scale;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c libc/stdlib.c -o bin/stdlib.o
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c libc/syscall.c -o bin/syscall.o
|
||||
nasm -f elf64 crt0.asm -o bin/crt0.o
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c about.c -o bin/about.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/about.o -o bin/about.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c beep.c -o bin/beep.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/beep.o -o bin/beep.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c browser.c -o bin/browser.o
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c nanojpeg.c -o bin/nanojpeg.o
|
||||
nanojpeg.c: In function 'njGetVLC':
|
||||
nanojpeg.c:685:24: warning: left shift of negative value [-Wshift-negative-value]
|
||||
685 | value += ((-1) << bits) + 1;
|
||||
| ^~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/browser.o bin/nanojpeg.o -o bin/browser.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c calculator.c -o bin/calculator.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/calculator.o -o bin/calculator.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c cat.c -o bin/cat.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/cat.o -o bin/cat.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c cc.c -o bin/cc.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/cc.o -o bin/cc.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c clear.c -o bin/clear.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/clear.o -o bin/clear.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c clock.c -o bin/clock.o
|
||||
clock.c: In function 'clock_paint':
|
||||
clock.c:89:36: warning: comparison of integer expressions of different signedness: 'tab_t' and 'int' [-Wsign-compare]
|
||||
89 | uint32_t bg = (current_tab == i) ? COLOR_TAB_ACTIVE : COLOR_DARK_PANEL;
|
||||
| ^~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/clock.o -o bin/clock.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c cowsay.c -o bin/cowsay.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/cowsay.o -o bin/cowsay.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c cp.c -o bin/cp.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/cp.o -o bin/cp.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c crash.c -o bin/crash.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/crash.o -o bin/crash.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c curl.c -o bin/curl.o
|
||||
curl.c: In function 'main':
|
||||
curl.c:60:9: warning: unused variable 'host_len' [-Wunused-variable]
|
||||
60 | int host_len = i;
|
||||
| ^~~~~~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/curl.o -o bin/curl.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c date.c -o bin/date.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/date.o -o bin/date.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c echo.c -o bin/echo.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/echo.o -o bin/echo.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c hello.c -o bin/hello.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/hello.o -o bin/hello.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c help.c -o bin/help.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/help.o -o bin/help.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c ls.c -o bin/ls.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/ls.o -o bin/ls.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c man.c -o bin/man.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/man.o -o bin/man.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c markdown.c -o bin/markdown.o
|
||||
markdown.c:59:12: warning: 'md_strncpy' defined but not used [-Wunused-function]
|
||||
59 | static int md_strncpy(char *dest, const char *src, int n) {
|
||||
| ^~~~~~~~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/markdown.o -o bin/markdown.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c math.c -o bin/math.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/math.o -o bin/math.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c meminfo.c -o bin/meminfo.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/meminfo.o -o bin/meminfo.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c minesweeper.c -o bin/minesweeper.o
|
||||
minesweeper.c: In function 'minesweeper_handle_click':
|
||||
minesweeper.c:195:50: warning: unused parameter 'win' [-Wunused-parameter]
|
||||
195 | static void minesweeper_handle_click(ui_window_t win, int x, int y, int button) {
|
||||
| ~~~~~~~~~~~~^~~
|
||||
minesweeper.c: At top level:
|
||||
minesweeper.c:17:13: warning: 'debug_print' defined but not used [-Wunused-function]
|
||||
17 | static void debug_print(const char *msg) {
|
||||
| ^~~~~~~~~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/minesweeper.o -o bin/minesweeper.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c mkdir.c -o bin/mkdir.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/mkdir.o -o bin/mkdir.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c mv.c -o bin/mv.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/mv.o -o bin/mv.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c net.c -o bin/net.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/net.o -o bin/net.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c notepad.c -o bin/notepad.o
|
||||
notepad.c: In function 'notepad_key':
|
||||
notepad.c:149:37: warning: unused parameter 'win' [-Wunused-parameter]
|
||||
149 | static void notepad_key(ui_window_t win, int h, char c) {
|
||||
| ~~~~~~~~~~~~^~~
|
||||
notepad.c: In function 'main':
|
||||
notepad.c:234:14: warning: unused parameter 'argc' [-Wunused-parameter]
|
||||
234 | int main(int argc, char **argv) {
|
||||
| ~~~~^~~~
|
||||
notepad.c:234:27: warning: unused parameter 'argv' [-Wunused-parameter]
|
||||
234 | int main(int argc, char **argv) {
|
||||
| ~~~~~~~^~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/notepad.o -o bin/notepad.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c paint.c -o bin/paint.o
|
||||
paint.c: In function 'wm_show_message':
|
||||
paint.c:156:41: warning: unused parameter 'title' [-Wunused-parameter]
|
||||
156 | static void wm_show_message(const char *title, const char *msg) {
|
||||
| ~~~~~~~~~~~~^~~~~
|
||||
paint.c:156:60: warning: unused parameter 'msg' [-Wunused-parameter]
|
||||
156 | static void wm_show_message(const char *title, const char *msg) {
|
||||
| ~~~~~~~~~~~~^~~
|
||||
paint.c: At top level:
|
||||
paint.c:38:13: warning: 'debug_print' defined but not used [-Wunused-function]
|
||||
38 | static void debug_print(const char *msg) {
|
||||
| ^~~~~~~~~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/paint.o -o bin/paint.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c pci_list.c -o bin/pci_list.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/pci_list.o -o bin/pci_list.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c ping.c -o bin/ping.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/ping.o -o bin/ping.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c pwd.c -o bin/pwd.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/pwd.o -o bin/pwd.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c reboot.c -o bin/reboot.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/reboot.o -o bin/reboot.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c rm.c -o bin/rm.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/rm.o -o bin/rm.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c settings.c -o bin/settings.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/settings.o bin/nanojpeg.o -o bin/settings.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c shutdown.c -o bin/shutdown.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/shutdown.o -o bin/shutdown.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c sweden.c -o bin/sweden.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/sweden.o -o bin/sweden.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c sysfetch.c -o bin/sysfetch.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/sysfetch.o -o bin/sysfetch.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c telnet.c -o bin/telnet.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/telnet.o -o bin/telnet.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c touch.c -o bin/touch.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/touch.o -o bin/touch.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c txtedit.c -o bin/txtedit.o
|
||||
txtedit.c: In function 'editor_paint':
|
||||
txtedit.c:330:10: warning: unused variable 'status_text' [-Wunused-variable]
|
||||
330 | char status_text[128];
|
||||
| ^~~~~~~~~~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/txtedit.o -o bin/txtedit.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c uptime.c -o bin/uptime.o
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/uptime.o -o bin/uptime.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -c viewer.c -o bin/viewer.o
|
||||
viewer.c: In function 'viewer_handle_click':
|
||||
viewer.c:104:45: warning: unused parameter 'win' [-Wunused-parameter]
|
||||
104 | static void viewer_handle_click(ui_window_t win, int x, int y) {
|
||||
| ~~~~~~~~~~~~^~~
|
||||
x86_64-elf-ld -m elf_x86_64 -nostdlib -static -no-pie -Ttext=0x40000000 --no-dynamic-linker -z text -z max-page-size=0x1000 -e _start bin/libui.o bin/stdlib.o bin/syscall.o bin/crt0.o bin/viewer.o bin/nanojpeg.o -o bin/viewer.elf
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -Wno-error -Idoom -c doom/am_map.c -o bin/am_map.o
|
||||
doom/am_map.c: In function 'AM_initVariables':
|
||||
doom/am_map.c:427:5: warning: missing initializer for field 'data4' of 'event_t' [-Wmissing-field-initializers]
|
||||
427 | static event_t st_notify = { ev_keyup, AM_MSGENTERED, 0, 0 };
|
||||
| ^~~~~~
|
||||
In file included from doom/st_stuff.h:25,
|
||||
from doom/am_map.c:27:
|
||||
doom/d_event.h:67:30: note: 'data4' declared here
|
||||
67 | int data1, data2, data3, data4;
|
||||
| ^~~~~
|
||||
doom/am_map.c: In function 'AM_Stop':
|
||||
doom/am_map.c:543:5: warning: missing initializer for field 'data4' of 'event_t' [-Wmissing-field-initializers]
|
||||
543 | static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED, 0 };
|
||||
| ^~~~~~
|
||||
doom/d_event.h:67:30: note: 'data4' declared here
|
||||
67 | int data1, data2, data3, data4;
|
||||
| ^~~~~
|
||||
doom/am_map.c: In function 'AM_drawThings':
|
||||
doom/am_map.c:1293:9: warning: unused parameter 'colorrange' [-Wunused-parameter]
|
||||
1293 | int colorrange)
|
||||
| ~~~~~~^~~~~~~~~~
|
||||
x86_64-elf-gcc -Wall -Wextra -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-80387 -mno-mmx -mno-sse -mno-sse2 -mno-red-zone -Ilibc -Wno-error -Idoom -c doom/boredos_libc.c -o bin/boredos_libc.o
|
||||
doom/boredos_libc.c:6:27: error: 'false' undeclared here (not in a function)
|
||||
6 | static FILE _stderr = {2, false, false};
|
||||
| ^~~~~
|
||||
doom/boredos_libc.c:3:1: note: 'false' is defined in header '<stdbool.h>'; this is probably fixable by adding '#include <stdbool.h>'
|
||||
2 | #include <syscall.h>
|
||||
+++ |+#include <stdbool.h>
|
||||
3 |
|
||||
doom/boredos_libc.c:6:1: warning: missing initializer for field 'eof' of 'FILE' [-Wmissing-field-initializers]
|
||||
6 | static FILE _stderr = {2, false, false};
|
||||
| ^~~~~~
|
||||
In file included from doom/boredos_libc.c:1:
|
||||
doom/boredos_libc.h:17:9: note: 'eof' declared here
|
||||
17 | int eof;
|
||||
| ^~~
|
||||
doom/boredos_libc.c:7:1: warning: missing initializer for field 'eof' of 'FILE' [-Wmissing-field-initializers]
|
||||
7 | static FILE _stdout = {1, false, false};
|
||||
| ^~~~~~
|
||||
doom/boredos_libc.h:17:9: note: 'eof' declared here
|
||||
17 | int eof;
|
||||
| ^~~
|
||||
doom/boredos_libc.c: In function 'fread':
|
||||
doom/boredos_libc.c:37:25: error: 'true' undeclared (first use in this function)
|
||||
37 | stream->error = true;
|
||||
| ^~~~
|
||||
doom/boredos_libc.c:37:25: note: 'true' is defined in header '<stdbool.h>'; this is probably fixable by adding '#include <stdbool.h>'
|
||||
doom/boredos_libc.c:37:25: note: each undeclared identifier is reported only once for each function it appears in
|
||||
doom/boredos_libc.c: In function 'fwrite':
|
||||
doom/boredos_libc.c:52:25: error: 'true' undeclared (first use in this function)
|
||||
52 | stream->error = true;
|
||||
| ^~~~
|
||||
doom/boredos_libc.c:52:25: note: 'true' is defined in header '<stdbool.h>'; this is probably fixable by adding '#include <stdbool.h>'
|
||||
doom/boredos_libc.c: In function 'rename':
|
||||
doom/boredos_libc.c:73:24: warning: unused parameter 'oldpath' [-Wunused-parameter]
|
||||
73 | int rename(const char *oldpath, const char *newpath) {
|
||||
| ~~~~~~~~~~~~^~~~~~~
|
||||
doom/boredos_libc.c:73:45: warning: unused parameter 'newpath' [-Wunused-parameter]
|
||||
73 | int rename(const char *oldpath, const char *newpath) {
|
||||
| ~~~~~~~~~~~~^~~~~~~
|
||||
doom/boredos_libc.c: In function 'mkdir':
|
||||
doom/boredos_libc.c:94:37: warning: unused parameter 'mode' [-Wunused-parameter]
|
||||
94 | int mkdir(const char *pathname, int mode) {
|
||||
| ~~~~^~~~
|
||||
doom/boredos_libc.c: In function 'access':
|
||||
doom/boredos_libc.c:98:38: warning: unused parameter 'mode' [-Wunused-parameter]
|
||||
98 | int access(const char *pathname, int mode) {
|
||||
| ~~~~^~~~
|
||||
doom/boredos_libc.c: In function 'fprintf':
|
||||
doom/boredos_libc.c:179:19: warning: unused parameter 'stream' [-Wunused-parameter]
|
||||
179 | int fprintf(FILE *stream, const char *format, ...) { return 0; }
|
||||
| ~~~~~~^~~~~~
|
||||
doom/boredos_libc.c:179:39: warning: unused parameter 'format' [-Wunused-parameter]
|
||||
179 | int fprintf(FILE *stream, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~~~~
|
||||
doom/boredos_libc.c: In function 'sprintf':
|
||||
doom/boredos_libc.c:180:19: warning: unused parameter 'str' [-Wunused-parameter]
|
||||
180 | int sprintf(char *str, const char *format, ...) { return 0; }
|
||||
| ~~~~~~^~~
|
||||
doom/boredos_libc.c:180:36: warning: unused parameter 'format' [-Wunused-parameter]
|
||||
180 | int sprintf(char *str, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~~~~
|
||||
doom/boredos_libc.c: In function 'snprintf':
|
||||
doom/boredos_libc.c:181:20: warning: unused parameter 'str' [-Wunused-parameter]
|
||||
181 | int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
|
||||
| ~~~~~~^~~
|
||||
doom/boredos_libc.c:181:32: warning: unused parameter 'size' [-Wunused-parameter]
|
||||
181 | int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~^~~~
|
||||
doom/boredos_libc.c:181:50: warning: unused parameter 'format' [-Wunused-parameter]
|
||||
181 | int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~~~~
|
||||
doom/boredos_libc.c: In function 'vsnprintf':
|
||||
doom/boredos_libc.c:182:21: warning: unused parameter 'str' [-Wunused-parameter]
|
||||
182 | int vsnprintf(char *str, size_t size, const char *format, va_list ap) { return 0; }
|
||||
| ~~~~~~^~~
|
||||
doom/boredos_libc.c:182:33: warning: unused parameter 'size' [-Wunused-parameter]
|
||||
182 | int vsnprintf(char *str, size_t size, const char *format, va_list ap) { return 0; }
|
||||
| ~~~~~~~^~~~
|
||||
doom/boredos_libc.c:182:51: warning: unused parameter 'format' [-Wunused-parameter]
|
||||
182 | int vsnprintf(char *str, size_t size, const char *format, va_list ap) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~~~~
|
||||
doom/boredos_libc.c:182:67: warning: unused parameter 'ap' [-Wunused-parameter]
|
||||
182 | int vsnprintf(char *str, size_t size, const char *format, va_list ap) { return 0; }
|
||||
| ~~~~~~~~^~
|
||||
doom/boredos_libc.c: In function 'sscanf':
|
||||
doom/boredos_libc.c:183:24: warning: unused parameter 'str' [-Wunused-parameter]
|
||||
183 | int sscanf(const char *str, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~
|
||||
doom/boredos_libc.c:183:41: warning: unused parameter 'format' [-Wunused-parameter]
|
||||
183 | int sscanf(const char *str, const char *format, ...) { return 0; }
|
||||
| ~~~~~~~~~~~~^~~~~~
|
||||
make[1]: *** [bin/boredos_libc.o] Error 1
|
||||
rm bin/pwd.o bin/minesweeper.o bin/ls.o bin/echo.o bin/pci_list.o bin/date.o bin/mkdir.o bin/help.o bin/markdown.o bin/cc.o bin/sweden.o bin/rm.o bin/notepad.o bin/man.o bin/clock.o bin/clear.o bin/cat.o bin/cp.o bin/paint.o bin/crash.o bin/reboot.o bin/beep.o bin/meminfo.o bin/net.o bin/calculator.o bin/cowsay.o bin/telnet.o bin/hello.o bin/math.o bin/curl.o bin/uptime.o bin/about.o bin/sysfetch.o bin/ping.o bin/mv.o bin/txtedit.o bin/touch.o bin/shutdown.o
|
||||
make: *** [build/boredos.elf] Error 2
|
||||
BIN
build/cmd.o
BIN
build/e1000.o
BIN
build/explorer.o
BIN
build/fat32.o
BIN
build/graphics.o
BIN
build/idt.o
BIN
build/main.o
BIN
build/pci.o
BIN
build/platform.o
BIN
build/ps2.o
BIN
build/rtc.o
33
docs/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
<div align="center">
|
||||
<h1>BoredOS Documentation</h1>
|
||||
<p><em>Internal guides, architecture, and application development.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
Welcome to the internal documentation for BoredOS! This directory contains detailed guides on how the OS functions, how to build it, and how to develop applications for it.
|
||||
|
||||
## 📚 Table of Contents
|
||||
|
||||
The documentation is organized into three main categories:
|
||||
|
||||
### 1. 🏗️ [Architecture](architecture/)
|
||||
Explains the logical layout of the kernel and internal components.
|
||||
- [`Core`](architecture/core.md): Kernel source layout and the boot process (Limine, Multiboot2).
|
||||
- [`Memory`](architecture/memory.md): Physical Memory Management (PMM) and Virtual Memory Management (VMM).
|
||||
- [`Filesystem`](architecture/filesystem.md): Virtual File System (VFS) and the RAM-based FAT32 simulation.
|
||||
- [`Window Manager`](architecture/window_manager.md): How the built-in Window Manager natively handles graphics, events, and compositing.
|
||||
|
||||
### 2. 🔨 [Building and Deployment](build/)
|
||||
Instructions for compiling the OS from source.
|
||||
- [`Toolchain`](build/toolchain.md): Prerequisites and cross-compiler setup (`x86_64-elf-gcc`, `nasm`, `xorriso`).
|
||||
- [`Usage`](build/usage.md): Understanding the Makefile targets, QEMU emulation, and flashing to bare metal hardware.
|
||||
|
||||
### 3. 🚀 [Application Development](appdev/)
|
||||
The SDK and toolchain guides for creating your own `.elf` userland binaries.
|
||||
- [`SDK Reference`](appdev/sdk_reference.md): Explanation of the custom `libc` wrappers (`stdlib.h`, `string.h`) and system calls.
|
||||
- [`UI API`](appdev/ui_api.md): Drawing on the screen, creating windows, and polling the event loop using `libui.h`.
|
||||
- [`Custom Apps`](appdev/custom_apps.md): A step-by-step tutorial on writing a new graphical C application, editing the Makefile, and bundling it into the ISO.
|
||||
- [`Example Apps`](appdev/examples/README.md): A collection of sample C applications ranging from basic terminal output to advanced TCP networking.
|
||||
|
||||
---
|
||||
90
docs/appdev/custom_apps.md
Normal file
@@ -0,0 +1,90 @@
|
||||
<div align="center">
|
||||
<h1>Creating a Custom App</h1>
|
||||
<p><em>A step-by-step tutorial on writing a new graphical C application.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
This guide explains how to write a new "Hello World" application locally, compile it as an `.elf` binary into the `bin/` folder, and launch it inside BoredOS.
|
||||
|
||||
> [!TIP]
|
||||
> **Looking for working code?** Check out the [Examples Directory](examples/README.md) for full source code demonstrating basic CLI, Windows, Animations, and TCP Networking.
|
||||
|
||||
## 📝 Step 1: Write the C Source
|
||||
|
||||
Applications reside entirely in the `src/userland/` directory. Create a new file, for example, `src/userland/gui/hello.c`.
|
||||
|
||||
> [!TIP]
|
||||
> Group CLI apps into `src/userland/cli/` and windowed apps into `src/userland/gui/` for organization.
|
||||
|
||||
```c
|
||||
// src/userland/gui/hello.c
|
||||
#include <stdlib.h>
|
||||
#include <libui.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(void) {
|
||||
// Attempt to open a 300x200 window
|
||||
ui_window_t wid = ui_window_create("My Custom App", 100, 100, 300, 200);
|
||||
if (wid < 0) {
|
||||
printf("Error creating window!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Write text in center
|
||||
ui_draw_string(wid, 50, 90, "Hello, BoredOS!!", 0xFFFFFFFF);
|
||||
|
||||
// Commit drawing to screen
|
||||
ui_mark_dirty(wid, 0, 0, 300, 200);
|
||||
|
||||
gui_event_t event;
|
||||
while (1) {
|
||||
if (ui_get_event(wid, &event)) {
|
||||
if (event.type == GUI_EVENT_CLOSE) {
|
||||
break; // Exit loop if 'X' is clicked
|
||||
}
|
||||
}
|
||||
|
||||
sys_yield();
|
||||
}
|
||||
|
||||
return 0; // Returning 0 smoothly exits the process via crt0.asm
|
||||
}
|
||||
```
|
||||
|
||||
## ⚙️ Step 2: Edit the Makefile
|
||||
|
||||
Now you need to tell the build system to compile `hello.c`. Fortunately, the `src/userland/Makefile` is designed to detect new C files largely automatically!
|
||||
|
||||
1. Open `src/userland/Makefile`.
|
||||
2. Find the line specifying `APP_SOURCES_FULL`:
|
||||
```make
|
||||
APP_SOURCES_FULL = $(wildcard cli/*.c gui/*.c sys/*.c games/*.c *.c)
|
||||
```
|
||||
Since you placed the file in `gui/hello.c`, the wildcard logic will pick it up automatically.
|
||||
3. The Makefile will generate `bin/hello.elf` during the build phase.
|
||||
|
||||
## 📦 Step 3: Bundle it into the OS
|
||||
|
||||
The main overarching `Makefile` (in the project root) takes binaries from `src/userland/bin/*.elf` and places them into the `iso_root/bin/` directory, while also adding them to `limine.conf` as loadable boot modules.
|
||||
|
||||
1. Go back to the root of the OS:
|
||||
```sh
|
||||
cd ../..
|
||||
```
|
||||
2. Compile the entire project to build the ISO and test in QEMU:
|
||||
```sh
|
||||
make clean && make run
|
||||
```
|
||||
|
||||
## 🚀 Step 4: Run it inside BoredOS
|
||||
|
||||
1. When BoredOS boots, launch the **Terminal** application.
|
||||
2. The OS automatically maps built applications to standard shell commands. Simply type your application's filename (without the `.elf` extension).
|
||||
3. Type `hello` in the terminal and press Enter.
|
||||
4. Your custom window will appear!
|
||||
|
||||
> [!NOTE]
|
||||
> You can also open your app by opening the file explorer, navigating to the `bin` directory, and double-clicking the executable.
|
||||
|
||||
---
|
||||
52
docs/appdev/examples/01_hello_cli.md
Normal file
@@ -0,0 +1,52 @@
|
||||
<div align="center">
|
||||
<h1>Example 01: Hello CLI</h1>
|
||||
<p><em>The absolute basics. Writing a terminal program.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
This example demonstrates the bare minimum structure of a BoredOS application that outputs text to the standard output (usually the Terminal executing the binary).
|
||||
|
||||
## 📝 Concepts Introduced
|
||||
* Including `stdlib.h` for basic IO.
|
||||
* The `main()` entry point.
|
||||
* Using `printf()` for formatted output.
|
||||
|
||||
---
|
||||
|
||||
## 💻 The Code (`src/userland/cli/hello_world.c`)
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Standard library initialization is handled automatically by crt0.asm
|
||||
|
||||
// Print a simple string to the terminal
|
||||
printf("Hello, World from BoredOS Userland!\n");
|
||||
|
||||
// Print some formatted data
|
||||
int favorite_number = 67;
|
||||
printf("Did you know my favorite number is %d?\n", favorite_number);
|
||||
|
||||
// Returning from main automatically terminates the process cleanly
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 🛠️ How it Works
|
||||
|
||||
1. **`#include <stdlib.h>`**: We include the SDK's standard library header which gives us access to `printf`.
|
||||
2. **`int main(...)`**: Every process begins execution here (managed transparently by `crt0.asm`).
|
||||
3. **`printf(...)`**: The SDK routes this call internally directly to the `SYS_WRITE` system call, making it available on the terminal.
|
||||
4. **`return 0`**: A successful exit code.
|
||||
|
||||
## 🚀 Running It
|
||||
|
||||
If you build the project, you can open the Terminal and type:
|
||||
```sh
|
||||
/ # hello_world
|
||||
Hello, World from BoredOS Userland!
|
||||
Did you know my favorite number is 67?
|
||||
/ #
|
||||
```
|
||||
71
docs/appdev/examples/02_basic_window.md
Normal file
@@ -0,0 +1,71 @@
|
||||
<div align="center">
|
||||
<h1>Example 02: Basic Window</h1>
|
||||
<p><em>An introduction to libui and creating graphical apps.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
This example demonstrates how to create an empty window that stays active on the screen until the user explicitly closes it by clicking the 'X' button.
|
||||
|
||||
## 📝 Concepts Introduced
|
||||
* Including `libui.h` and the event structure.
|
||||
* Creating a `ui_window_t` handle.
|
||||
* Creating an infinite event loop using `ui_get_event()`.
|
||||
* Yielding CPU time to the kernel via `sys_yield()`.
|
||||
|
||||
---
|
||||
|
||||
## 💻 The Code (`src/userland/gui/basic_window.c`)
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <libui.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(void) {
|
||||
// 1. Ask the Window Manager to create a new window
|
||||
// Arguments are: Title, X Position, Y Position, Width, Height
|
||||
ui_window_t wid = ui_window_create("My First GUI", 100, 100, 400, 300);
|
||||
|
||||
if (wid < 0) {
|
||||
printf("Failed to create the window!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 2. Define our event object
|
||||
gui_event_t event;
|
||||
|
||||
// 3. Enter the main event loop
|
||||
while (1) {
|
||||
// ui_get_event is non-blocking. It returns true if an event was waiting.
|
||||
if (ui_get_event(wid, &event)) {
|
||||
|
||||
// Check what type of event occurred
|
||||
if (event.type == GUI_EVENT_CLOSE) {
|
||||
// The user clicked the 'X' button in the titlebar!
|
||||
printf("Window closed cleanly by user.\n");
|
||||
break; // Break the infinite loop
|
||||
}
|
||||
}
|
||||
|
||||
// 4. CRITICAL: Yield the remainder of our timeslice
|
||||
// If we don't do this, the while(1) loop will consume 100% of the CPU
|
||||
// and starve the rest of the OS!
|
||||
sys_yield();
|
||||
}
|
||||
|
||||
// Returning from main will automatically destroy the window and exit the process.
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 🛠️ How it Works
|
||||
|
||||
1. **Window Handle (`wid`)**: `ui_window_create` sends a request to the kernel. The kernel allocates the memory for the window and returns a numerical ID (the handle) that we use for all future interactions with that specific window.
|
||||
2. **The Event Loop**: Graphical programs run forever until closed. The `while (1)` loop serves this purpose.
|
||||
3. **Polling**: `ui_get_event` asks the kernel, "Hey, did the user click my window or press a key since the last time I asked?". It is non-blocking, so it immediately returns `false` if nothing happened.
|
||||
4. **CPU Yielding**: Since we are constantly polling in a tight loop, we call `sys_yield()` at the end of the loop frame. This politely tells the OS scheduler, "I'm done checking for events, go ahead and let another program run for a bit."
|
||||
|
||||
## 🚀 Running It
|
||||
|
||||
Launch the Terminal and type `basic_window`. You'll see an empty window appear that you can move around the screen!
|
||||
92
docs/appdev/examples/03_bouncing_ball.md
Normal file
@@ -0,0 +1,92 @@
|
||||
<div align="center">
|
||||
<h1>Example 03: Bouncing Ball</h1>
|
||||
<p><em>Animating graphics and managing application state.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
This example builds upon the `02_basic_window` guide. It demonstrates how to constantly update the screen to simulate a bouncing square moving freely inside the window bounds.
|
||||
|
||||
## 📝 Concepts Introduced
|
||||
* Maintaining application state across frames (Velocity/Position).
|
||||
* Drawing primitives (`ui_fill_rect`, `ui_draw_string`).
|
||||
* The importance of clearing the screen on a new frame.
|
||||
* Explicitly forcing standard visual updates via `ui_mark_dirty()`.
|
||||
|
||||
---
|
||||
|
||||
## 💻 The Code (`src/userland/gui/bounce.c`)
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <libui.h>
|
||||
#include <syscall.h>
|
||||
|
||||
// Window Dimensions
|
||||
#define W_WIDTH 400
|
||||
#define W_HEIGHT 300
|
||||
// Square Dimensions
|
||||
#define SQ_SIZE 30
|
||||
|
||||
int main(void) {
|
||||
ui_window_t wid = ui_window_create("Bouncing Box Animation", 50, 50, W_WIDTH, W_HEIGHT);
|
||||
if (wid < 0) return 1;
|
||||
|
||||
// Define object state variables
|
||||
int pos_x = 50;
|
||||
int pos_y = 50;
|
||||
int vel_x = 2; // Move 2 pixels per frame horizontally
|
||||
int vel_y = 2; // Move 2 pixels per frame vertically
|
||||
|
||||
gui_event_t event;
|
||||
while (1) {
|
||||
// 1. Process Events
|
||||
while (ui_get_event(wid, &event)) {
|
||||
if (event.type == GUI_EVENT_CLOSE) {
|
||||
return 0; // Exit cleanly
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Physics & Logic Update
|
||||
pos_x += vel_x;
|
||||
pos_y += vel_y;
|
||||
|
||||
// Collision logic (Bounce off edges)
|
||||
// The window has a 20px title bar, so the usable client height is W_HEIGHT - 20.
|
||||
if (pos_x <= 0 || pos_x + SQ_SIZE >= W_WIDTH) {
|
||||
vel_x = -vel_x; // Reverse horizontal direction
|
||||
}
|
||||
if (pos_y <= 0 || pos_y + SQ_SIZE >= W_HEIGHT - 20) {
|
||||
vel_y = -vel_y; // Reverse vertical direction
|
||||
}
|
||||
|
||||
// 3. Rendering Update
|
||||
// Step A: Clear the entire background to Black (0xFF000000)
|
||||
ui_draw_rect(wid, 0, 0, W_WIDTH, W_HEIGHT, 0xFF000000);
|
||||
|
||||
// Step B: Draw our shape in Red (0xFFFF0000) at the new position
|
||||
ui_draw_rect(wid, pos_x, pos_y, SQ_SIZE, SQ_SIZE, 0xFFFF0000);
|
||||
|
||||
// Step C: Draw some UI text over the animation in White
|
||||
ui_draw_string(wid, 10, 10, "BoredOS Animation Demo!", 0xFFFFFFFF);
|
||||
|
||||
// Step D: Instruct the compositor to flush our drawing buffer to the physical screen
|
||||
ui_mark_dirty(wid, 0, 0, W_WIDTH, W_HEIGHT);
|
||||
|
||||
// 4. Yield and throttle
|
||||
sys_yield();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 🛠️ How it Works
|
||||
|
||||
1. **State Management**: We store `pos_x`, `pos_y`, `vel_x`, and `vel_y`. These variables represent the "physics" of our system. Notice that they update *outside* the event-checking logic so that the animation runs even if the user isn't clicking the mouse.
|
||||
2. **Screen Clearing**: We *must* fill the screen with black (`ui_draw_rect(wid, 0, 0, W_WIDTH, W_HEIGHT, ...)`). If we don't clear the screen, the red square will leave a permanent trailing smear everywhere it goes!
|
||||
3. **The Double Buffer**: `ui_draw_rect` and `ui_draw_string` do not immediately appear on your monitor. They just color a hidden buffer within the kernel.
|
||||
4. **`ui_mark_dirty`**: This is the crucial command that tells the kernel Window Manager, "I'm done drawing my frame. Can you quickly copy my hidden buffer over to the real screen now?"
|
||||
|
||||
> [!WARNING]
|
||||
> Because `sys_yield()`'s pause duration depends heavily on CPU load and how many other processes are running (or QEMU emulation speed), tying physics/movement strictly to loops can make the game run faster on faster computers. Advanced developers will want to calculate delta time (time elapsed since the last frame) for smooth motion.
|
||||
92
docs/appdev/examples/04_tcp_client.md
Normal file
@@ -0,0 +1,92 @@
|
||||
<div align="center">
|
||||
<h1>Example 04: TCP HTTP Client</h1>
|
||||
<p><em>Utilizing lwIP to establish an outbound TCP connection.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
This advanced example demonstrates the steps required to use the raw network system calls to establish a connection with an external HTTP server and dump the response over the terminal.
|
||||
|
||||
## 📝 Concepts Introduced
|
||||
* Verifying the network state (`sys_network_is_initialized`, `sys_network_has_ip`).
|
||||
* Performing DNS lookups manually via `sys_dns_lookup`.
|
||||
* Managing strict TCP flow logic (`sys_tcp_connect`, send, block for receive).
|
||||
* Using the terminal `SYS_WRITE` output for debugging.
|
||||
|
||||
---
|
||||
|
||||
## 💻 The Code (`src/userland/cli/http_get.c`)
|
||||
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(void) {
|
||||
if (!sys_network_is_initialized() || !sys_network_has_ip()) {
|
||||
printf("Network is unreachable! Make sure you inited the network first!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 1. Resolve host name to IP
|
||||
const char *target_host = "boreddev.nl";
|
||||
net_ipv4_address_t server_ip;
|
||||
|
||||
printf("Resolving %s...\n", target_host);
|
||||
if (sys_dns_lookup(target_host, &server_ip) < 0) {
|
||||
printf("DNS Lookup failed.\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Resolved to: %d.%d.%d.%d\n", server_ip.bytes[0], server_ip.bytes[1],
|
||||
server_ip.bytes[2], server_ip.bytes[3]);
|
||||
|
||||
// 2. Establish a TCP connection on port 80 (HTTP)
|
||||
printf("Connecting...\n");
|
||||
if (sys_tcp_connect(&server_ip, 80) < 0) {
|
||||
printf("Connection failed.\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Connected! Sending GET request...\n");
|
||||
|
||||
// 3. Format and send the raw HTTP Request
|
||||
char request[256];
|
||||
strcpy(request, "GET / HTTP/1.1\r\nHost: ");
|
||||
strcat(request, target_host);
|
||||
strcat(request, "\r\nConnection: close\r\n\r\n");
|
||||
|
||||
if (sys_tcp_send(request, strlen(request)) < 0) {
|
||||
printf("Failed to send data.\n");
|
||||
sys_tcp_close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 4. Block and wait for response data
|
||||
char recv_buf[512];
|
||||
int bytes_received;
|
||||
|
||||
printf("\n--- RESPONSE ---\n");
|
||||
while ((bytes_received = sys_tcp_recv(recv_buf, sizeof(recv_buf) - 1)) > 0) {
|
||||
recv_buf[bytes_received] = '\0'; // Null-terminate the chunk
|
||||
printf("%s", recv_buf); // Print the chunk to stdout
|
||||
}
|
||||
|
||||
// 5. Cleanup
|
||||
printf("\n--- END RESPONSE ---\n");
|
||||
sys_tcp_close();
|
||||
printf("Connection closed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 🛠️ How it Works
|
||||
|
||||
1. **Network Setup**: First, we must ensure the host machine or QEMU environment gave BoredOS a valid IP address via DHCP. The `sys_network_has_ip()` check prevents our app from hanging trying to route data to nowhere.
|
||||
2. **DNS (`sys_dns_lookup`)**: Since we want to connect to a domain name, not a raw IP, we query the DNS server configured by the OS (which it received via DHCP).
|
||||
3. **Connection (`sys_tcp_connect`)**: We block the application thread while the OS performs the 3-way TCP handshake over port 80.
|
||||
4. **Payload (`sys_tcp_send`)**: We format a compliant HTTP/1.1 payload representing a simple GET request for the root directory `/`.
|
||||
5. **Chunked Receiving (`sys_tcp_recv`)**: The server's response might be larger than our `recv_buf` (512 bytes). Therefore, we loop. `sys_tcp_recv` blocks execution until data arrives. If it returns `0`, the remote server cleanly closed the connection (which happens automatically because we specified `Connection: close` in our request payload!).
|
||||
|
||||
## 🚀 Running It
|
||||
|
||||
Make sure QEMU is running with networking enabled. Launch the terminal and type `http_get`. You will see the raw headers and HTML source of the target webpage scroll down the CLI interface!
|
||||
28
docs/appdev/examples/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
<div align="center">
|
||||
<h1>Example Applications</h1>
|
||||
<p><em>From basic output to complex Graphical and Network applications.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
Welcome to the examples directory! These guides are designed to help you understand how to write C applications for the BoredOS userland, utilizing the custom `libc` SDK.
|
||||
|
||||
The examples are listed in order of increasing complexity. Click on a tutorial to view the complete source code and an explanation of the concepts it introduces.
|
||||
|
||||
## 🟢 Beginner
|
||||
|
||||
* **[`01_hello_cli.md`](01_hello_cli.md)**: The absolute basics. Learn how to write a simple Terminal program that outputs text and processes standard system calls.
|
||||
* **[`02_basic_window.md`](02_basic_window.md)**: An introduction to `libui.h`. Learn how to create an empty window, set up a basic event loop, and handle the "Close" button cleanly.
|
||||
|
||||
## 🟡 Intermediate
|
||||
|
||||
* **[`03_bouncing_ball.md`](03_bouncing_ball.md)**: Dive deeper into graphical rendering. This example introduces the `ui_mark_dirty` command, framerate independence via `sys_yield()`, and state management to animate a shape moving around the screen and bouncing off the window edges.
|
||||
|
||||
## 🔴 Advanced
|
||||
|
||||
* **[`04_tcp_client.md`](04_tcp_client.md)**: Using the lwIP networking stack. This example demonstrates how to perform a DNS lookup, connect to an external server over TCP (like an HTTP server), send a raw request, and print the response to the terminal.
|
||||
|
||||
---
|
||||
|
||||
> [!TIP]
|
||||
> If you want to test these out, simply create a new `.c` file in `src/userland/cli/` (for terminal apps) or `src/userland/gui/` (for windowed apps), paste the example code, then run `make clean && make run` from the project root!
|
||||
157
docs/appdev/sdk_reference.md
Normal file
@@ -0,0 +1,157 @@
|
||||
<div align="center">
|
||||
<h1>Userland SDK Reference</h1>
|
||||
<p><em>Comprehensive manual for custom libc and system calls in BoredOS.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
BoredOS provides a custom `libc` implementation necessary for writing userland applications (`.elf` binaries). By avoiding a full-blown standard library like `glibc`, the OS ensures a minimal executable footprint tailored strictly to the existing kernel features.
|
||||
|
||||
All headers are located in `src/userland/libc/`.
|
||||
|
||||
## 📚 Standard Library (`stdlib.h` & `string.h`)
|
||||
|
||||
The standard library wrappers provide memory management, string manipulation, and basic IO formatting without needing direct syscalls.
|
||||
|
||||
### Memory Allocation
|
||||
* `void* malloc(size_t size);` - Allocate a block of memory on the heap.
|
||||
* `void free(void* ptr);` - Free a previously allocated memory block.
|
||||
* `void* calloc(size_t nmemb, size_t size);` - Allocate and zero-out a block of memory for an array.
|
||||
* `void* realloc(void* ptr, size_t size);` - Resize an existing memory block.
|
||||
|
||||
### Memory Manipulation (`string.h`)
|
||||
* `void* memset(void *s, int c, size_t n);` - Fill a block of memory with a specific byte.
|
||||
* `void* memcpy(void *dest, const void *src, size_t n);` - Copy memory from source to destination.
|
||||
* `void* memmove(void *dest, const void *src, size_t n);` - Safely copy overlapping memory blocks.
|
||||
* `int memcmp(const void *s1, const void *s2, size_t n);` - Compare two memory blocks.
|
||||
|
||||
### String Utilities
|
||||
* `size_t strlen(const char *s);` - Get the length of a string.
|
||||
* `int strcmp(const char *s1, const char *s2);` - Compare two strings lexicographically.
|
||||
* `char* strcpy(char *dest, const char *src);` - Copy a string to a destination buffer.
|
||||
* `char* strcat(char *dest, const char *src);` - Concatenate two strings.
|
||||
|
||||
### Conversion and Formatting
|
||||
* `int atoi(const char *nptr);` - String to integer conversion.
|
||||
* `void itoa(int n, char *buf);` - Integer to string conversion.
|
||||
|
||||
### Input / Output
|
||||
* `void puts(const char *s);` - Print a string followed by a newline to the standard output.
|
||||
* `void printf(const char *fmt, ...);` - Formatted print to standard output (supports `%d`, `%s`, `%x`, etc.).
|
||||
|
||||
### Process Control
|
||||
* `void exit(int status);` - Terminate the current process.
|
||||
* `void sleep(int ms);` - Pause execution for a specified number of milliseconds.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ System Calls (`syscall.h`)
|
||||
|
||||
For advanced operations, `syscall.h` provides direct wrappers into the kernel.
|
||||
|
||||
### Process & System Info
|
||||
* `void sys_exit(int status);` - Raw exit syscall.
|
||||
* `int sys_write(int fd, const char *buf, int len);` - Write to a file descriptor (usually fd 1 for stdout).
|
||||
* `void* sys_sbrk(int incr);` - Expand or shrink the process data segment (used internally by `malloc`).
|
||||
* `void sys_kill(int pid);` - Send a kill signal to a process.
|
||||
* `void sys_yield(void);` - Yield the remainder of the process's timeslice to the scheduler.
|
||||
* `int sys_system(int cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);` - Execute a privileged system command (e.g., reboot, shutdown, beep).
|
||||
* `int sys_get_os_info(os_info_t *info);` - Populate an `os_info_t` struct with version and environment details.
|
||||
* `uint64_t sys_get_shell_config(const char *key);` - Retrieve internal shell configuration values.
|
||||
* `void sys_set_text_color(uint32_t color);` - Set the raw CLI text output color.
|
||||
|
||||
### File System API (VFS)
|
||||
Interacting with files and directories using the Virtual File System.
|
||||
* `int sys_open(const char *path, const char *mode);` - Open a file, returning a file descriptor.
|
||||
* `int sys_read(int fd, void *buf, uint32_t len);` - Read from an open file.
|
||||
* `int sys_write_fs(int fd, const void *buf, uint32_t len);` - Write to an open file.
|
||||
* `void sys_close(int fd);` - Close an open file descriptor.
|
||||
* `int sys_seek(int fd, int offset, int whence);` - Reposition the file offset.
|
||||
* `uint32_t sys_tell(int fd);` - Get the current file offset.
|
||||
* `uint32_t sys_size(int fd);` - Get the total file size.
|
||||
* `int sys_delete(const char *path);` - Delete a file.
|
||||
* `int sys_mkdir(const char *path);` - Create a new directory.
|
||||
* `int sys_exists(const char *path);` - Check if a path exists on the filesystem.
|
||||
* `int sys_getcwd(char *buf, int size);` - Get the current working directory string.
|
||||
* `int sys_chdir(const char *path);` - Change the current working directory.
|
||||
* `int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries);` - List directory contents into an array of `FAT32_FileInfo` structs.
|
||||
* `int sys_get_file_info(const char *path, FAT32_FileInfo *info);` - Retrieve metadata for a specific file.
|
||||
|
||||
### Networking Stack API
|
||||
BoredOS includes lwIP for hardware TCP/UDP networking.
|
||||
|
||||
#### Configuration and Status
|
||||
* `int sys_network_init(void);` - Initialize the network stack.
|
||||
* `int sys_network_is_initialized(void);` - Check stack status.
|
||||
* `int sys_network_dhcp_acquire(void);` - Request an IP configuration from a DHCP server.
|
||||
* `int sys_network_has_ip(void);` - Check if the system has a valid IP address.
|
||||
* `int sys_network_get_mac(net_mac_address_t *mac);` - Get the physical MAC address of the NIC.
|
||||
* `int sys_network_get_nic_name(char *name_out);` - Get the name of the active network interface card.
|
||||
* `int sys_network_get_ip(net_ipv4_address_t *ip);` - Get current local IPv4 address.
|
||||
* `int sys_network_set_ip(const net_ipv4_address_t *ip);` - Manually assign a static IP.
|
||||
* `int sys_network_get_gateway(net_ipv4_address_t *ip);` - Get the default gateway IP.
|
||||
* `int sys_network_get_dns(net_ipv4_address_t *ip);` - Get the primary DNS server IP.
|
||||
* `int sys_set_dns_server(const net_ipv4_address_t *ip);` - Set the primary DNS server.
|
||||
* `int sys_get_dns_server(net_ipv4_address_t *ip);` - Retrieve configured DNS server.
|
||||
* `int sys_network_get_stat(int stat_type);` - Get network statistics (packets in/out, drops, etc.).
|
||||
* `void sys_network_force_unlock(void);` - Force release of network stack locks (use with caution).
|
||||
|
||||
#### Communication
|
||||
* `int sys_icmp_ping(const net_ipv4_address_t *dest_ip);` - Send an ICMP echo request.
|
||||
* `int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len);` - Send a raw UDP datagram.
|
||||
* `int sys_dns_lookup(const char *name, net_ipv4_address_t *out_ip);` - Resolve a hostname to an IPv4 address.
|
||||
* `int sys_tcp_connect(const net_ipv4_address_t *ip, uint16_t port);` - Establish a TCP connection to a remote host.
|
||||
* `int sys_tcp_send(const void *data, size_t len);` - Send data over an active TCP socket.
|
||||
* `int sys_tcp_recv(void *buf, size_t max_len);` - Receive data from a TCP socket (blocking).
|
||||
* `int sys_tcp_recv_nb(void *buf, size_t max_len);` - Receive data from a TCP socket (non-blocking).
|
||||
* `int sys_tcp_close(void);` - Close the active TCP socket.
|
||||
|
||||
---
|
||||
|
||||
## 📑 Core Data Structures
|
||||
|
||||
### `os_info_t`
|
||||
Contains detailed build and version information about the OS.
|
||||
```c
|
||||
typedef struct {
|
||||
char os_name[64];
|
||||
char os_version[64];
|
||||
char os_codename[64];
|
||||
char kernel_name[64];
|
||||
char kernel_version[64];
|
||||
char build_date[64];
|
||||
char build_time[64];
|
||||
char build_arch[64];
|
||||
} os_info_t;
|
||||
```
|
||||
|
||||
### `FAT32_FileInfo`
|
||||
Represents a filesystem entry.
|
||||
```c
|
||||
typedef struct {
|
||||
char name[256];
|
||||
uint32_t size;
|
||||
uint8_t is_directory;
|
||||
uint32_t start_cluster;
|
||||
uint16_t write_date;
|
||||
uint16_t write_time;
|
||||
} FAT32_FileInfo;
|
||||
```
|
||||
|
||||
### `ProcessInfo`
|
||||
Provides status information for an active process.
|
||||
```c
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
char name[64];
|
||||
uint64_t ticks;
|
||||
size_t used_memory;
|
||||
} ProcessInfo;
|
||||
```
|
||||
|
||||
### IP / MAC Addresses
|
||||
Wrappers for raw byte arrays.
|
||||
```c
|
||||
typedef struct { uint8_t bytes[6]; } net_mac_address_t;
|
||||
typedef struct { uint8_t bytes[4]; } net_ipv4_address_t;
|
||||
```
|
||||
105
docs/appdev/ui_api.md
Normal file
@@ -0,0 +1,105 @@
|
||||
<div align="center">
|
||||
<h1>UI API (<code>libui.h</code>)</h1>
|
||||
<p><em>Comprehensive manual for interacting with the Window Manager.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
The UI library (`libui.h`) is the sole mechanism for Graphical Userland Applications to draw to the screen and receive input events in BoredOS. It wraps `SYS_GUI` kernel calls.
|
||||
|
||||
## 🪟 Window Management
|
||||
|
||||
A "Window" is a reserved drawing canvas managed by the compositor.
|
||||
|
||||
* `ui_window_t ui_window_create(const char *title, int x, int y, int w, int h);`
|
||||
Creates a new window at `(x, y)` with dimensions `w`x`h`. Returns a window handle.
|
||||
**Flags** are currently embedded in the syscall; standard windows include decorations (titlebar, borders).
|
||||
* `void ui_window_set_title(ui_window_t win, const char *title);`
|
||||
Dynamically update the text displayed in the window's titlebar.
|
||||
* `void ui_window_set_resizable(ui_window_t win, bool resizable);`
|
||||
Enable or disable the user's ability to resize the window by dragging its edges.
|
||||
* `void ui_get_screen_size(uint64_t *out_w, uint64_t *out_h);`
|
||||
Query the global screen resolution of the display.
|
||||
|
||||
## 🎨 Drawing Primitives
|
||||
|
||||
All drawing functions write to an off-screen buffer associated with the window. **You must call `ui_mark_dirty()` to instruct the compositor to push your changes to the physical screen.**
|
||||
|
||||
* `void ui_draw_rect(ui_window_t win, int x, int y, int w, int h, uint32_t color);`
|
||||
Draw a solid filled rectangle.
|
||||
* `void ui_draw_rounded_rect_filled(ui_window_t win, int x, int y, int w, int h, int radius, uint32_t color);`
|
||||
Fill a rectangle with rounded corners of a specified `radius`.
|
||||
* `void ui_draw_image(ui_window_t win, int x, int y, int w, int h, uint32_t *image_data);`
|
||||
Blit a raw ARGB pixel buffer (`image_data`) directly into the window canvas.
|
||||
* `void ui_mark_dirty(ui_window_t win, int x, int y, int w, int h);`
|
||||
Mark a specific rectangular region of the window as "dirty". The Window Manager will redraw this area on the next compositing pass.
|
||||
|
||||
> [!TIP]
|
||||
> Colors are defined as 32-bit unsigned integers in **ARGB** format: `0xAARRGGBB`.
|
||||
> E.g., `0xFF000000` is opaque black, `0xFFFF0000` is opaque red.
|
||||
|
||||
## 🔤 Text Rendering
|
||||
|
||||
BoredOS provides multiple text rendering methodologies, including a default system font and scaled/bitmap alternatives.
|
||||
|
||||
* `void ui_draw_string(ui_window_t win, int x, int y, const char *str, uint32_t color);`
|
||||
Draw text using the default system typeface.
|
||||
* `void ui_draw_string_bitmap(ui_window_t win, int x, int y, const char *str, uint32_t color);`
|
||||
Draw text using a secondary fast bitmap font renderer.
|
||||
* `void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale);`
|
||||
Draw text scaled up or down by a floating-point multiplier.
|
||||
* `void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope);`
|
||||
Draw scaled text with an italic-like slope/shear applied.
|
||||
* `void ui_set_font(ui_window_t win, const char *path);`
|
||||
Load and set a custom `.ttf` or bitmap font from the filesystem for this window.
|
||||
|
||||
### Font Metrics
|
||||
Used for calculating layout bounds before drawing:
|
||||
* `uint32_t ui_get_string_width(const char *str);`
|
||||
* `uint32_t ui_get_font_height(void);`
|
||||
* `uint32_t ui_get_string_width_scaled(const char *str, float scale);`
|
||||
* `uint32_t ui_get_font_height_scaled(float scale);`
|
||||
|
||||
## 🔄 Event Handling
|
||||
|
||||
Applications must continuously poll for events inside an infinite `$while(1)` loop.
|
||||
|
||||
* `bool ui_get_event(ui_window_t win, gui_event_t *ev);`
|
||||
Returns `true` if an event was waiting in the queue, populating the `ev` structure. Returns `false` if the queue is empty.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Because `ui_get_event` is non-blocking, you must call `sys_yield();` inside your event loop if no event was received. In BoredOS's **Multi-Core (SMP)** architecture, failing to yield will pin a CPU core to 100% usage, potentially starving other processes.
|
||||
>
|
||||
> All UI syscalls are **Thread-Safe** at the kernel level via the global GUI spinlock.
|
||||
|
||||
### Graphical Event Structure
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
int type; // Specifies the event class (see below)
|
||||
int arg1; // Generic argument 1
|
||||
int arg2; // Generic argument 2
|
||||
int arg3; // Generic argument 3
|
||||
} gui_event_t;
|
||||
```
|
||||
|
||||
### Event Types & Arguments
|
||||
|
||||
| Event Constant | `type` ID | Trigger | `arg1` | `arg2` | `arg3` |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| `GUI_EVENT_NONE` | `0` | Empty event | - | - | - |
|
||||
| `GUI_EVENT_PAINT` | `1` | Window needs redrawing | - | - | - |
|
||||
| `GUI_EVENT_CLICK` | `2` | Mouse click down | X Coord | Y Coord | Button State |
|
||||
| `GUI_EVENT_RIGHT_CLICK` | `3` | Mouse right-click down | X Coord | Y Coord | Button State |
|
||||
| `GUI_EVENT_CLOSE` | `4` | User clicked 'X' button | - | - | - |
|
||||
| `GUI_EVENT_KEY` | `5` | Keyboard key pressed | Keycode | Modifiers | - |
|
||||
| `GUI_EVENT_KEYUP` | `10` | Keyboard key released | Keycode | Modifiers | - |
|
||||
| `GUI_EVENT_MOUSE_DOWN` | `6` | Generic mouse button down | X Coord | Y Coord | Button State |
|
||||
| `GUI_EVENT_MOUSE_UP` | `7` | Generic mouse button release | X Coord | Y Coord | Button State |
|
||||
| `GUI_EVENT_MOUSE_MOVE` | `8` | Mouse cursor moved | X Coord | Y Coord | - |
|
||||
| `GUI_EVENT_MOUSE_WHEEL` | `9` | Scroll wheel rotated | Scroll Delta | - | - |
|
||||
| `GUI_EVENT_RESIZE` | `11` | Window dimensions changed| New Width | New Height | - |
|
||||
|
||||
*(Note: Coordinate arguments (`arg1`, `arg2`) for mouse events are typically relative to the top-left corner of the window's client area).*
|
||||
|
||||
---
|
||||
58
docs/architecture/core.md
Normal file
@@ -0,0 +1,58 @@
|
||||
<div align="center">
|
||||
<h1>Core Architecture</h1>
|
||||
<p><em>Overview of BoredOS kernel layout, boot process, and userspace transition.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
BoredOS is a 64-bit hobbyist operating system designed for the x86_64 architecture. While it features kernel-space drivers and a built-in window manager, it supports fully-isolated userspace applications and includes a networking stack.
|
||||
|
||||
This document serves as an overview of the core architecture and the layout of the kernel source code.
|
||||
|
||||
## 📂 Source Code Layout (`src/`)
|
||||
|
||||
The OS heavily relies on module separation. The `src/` directory is logically split into several domains:
|
||||
|
||||
- **`arch/`**: Contains the assembly routines needed for bootstrapping the system (`boot.asm`) and setting up the CPU state for userland execution (`process_asm.asm`). It also handles architecture-specific mechanisms like the Global Descriptor Table (GDT) and Interrupt Descriptor Table (IDT).
|
||||
- **`core/`**: The initialization sequence of the OS lives here. `main.c` is the entry point from the bootloader. This directory also contains essential kernel utilities (`kutils.c`), panic handlers (`panic.c`), and built-in command parsing logic (`cmd.c`).
|
||||
- **`dev/`**: Device drivers. This includes the PCI scanner, disk management infrastructure, input drivers (keyboard and mouse), and the Real Time Clock (RTC).
|
||||
- **`fs/`**: Filesystem implementations. The system uses a Virtual File System (VFS) abstraction alongside an in-memory FAT32 filesystem with support for drives over ATA that are formatted as FAT32 (plain/MBR).
|
||||
- **`mem/`**: Physical and virtual memory management. It controls page frame allocation, paging, and kernel heap operations.
|
||||
- **`net/`**: The networking stack. BoredOS relies on `lwIP` for processing IPv4 and TCP/UDP traffic, interacting with a range of NICs via `net/nic/`.
|
||||
- **`sys/`**: System calls and process management. The ELF loader resides here, alongside the Symmetric Multi-Processing (**smp.c**) bringup and Local APIC (**lapic.c**) management logic.
|
||||
- **`wm/`**: The graphical subsystem. It handles drawing primitives, window structures, font rendering, and double-buffering.
|
||||
- **`userland/`**: Out-of-kernel components. This includes the custom SDK/compiler environment (`libc/`) and user applications (`cli/`, `gui/`, `games/`).
|
||||
|
||||
## 🚀 Boot Process
|
||||
|
||||
BoredOS uses **Limine** as its primary bootloader.
|
||||
|
||||
1. **Limine Initialization**: The machine firmware (BIOS or UEFI) loads Limine. Limine parses `limine.conf`, sets up an early graphical framebuffer, and reads the kernel ELF file into memory.
|
||||
2. **Multiboot2 & SMP Protocol**: The kernel expects the Limine boot protocol. It makes a specific **SMP Request** to Limine to locate and bring up all available CPU cores.
|
||||
3. **Kernel Entry (`main.c`)**: The entry point `_start` is called on the Bootstrap Processor (BSP). It initializes the serial port, GDT/IDT, memory management, and paging.
|
||||
4. **AP Bringup**: The BSP calls `smp_init()`, which sends the Startup Inter-Processor Interrupt (SIPI) sequence to all Application Processors (APs). Each AP initializes its own local GDT, TSS, and Page Tables before entering an idle loop.
|
||||
5. **Driver Initialization**: PCI buses are scanned, finding the network card or disk controllers. The filesystem is mounted.
|
||||
6. **Window Manager**: The UI is drawn on top of the Limine-provided framebuffer.
|
||||
|
||||
## 🧵 Multi-Core & Scheduling
|
||||
|
||||
BoredOS utilizes Symmetric Multi-Processing (SMP) to distribute workloads across all available CPU cores.
|
||||
|
||||
- **LAPIC & IPIs**: Each CPU has its own Local APIC. The kernel uses Inter-Processor Interrupts (IPIs) for inter-core communication, specifically for triggering the scheduler on other cores (`vector 0x41`).
|
||||
- **Scheduler**: A round-robin scheduler runs on each core. Processes are pinned to specific CPUs (CPU Affinity) to maintain cache locality. The BSP timer interrupt (`60Hz`) broadcasts a scheduling IPI to all core to ensure balanced execution.
|
||||
- **Spinlocks**: Since multiple cores can access kernel structures (VFS, Process List) simultaneously, the kernel uses **interrupt-safe spinlocks** to prevent race conditions.
|
||||
|
||||
## 🛡️ Userland Transition
|
||||
|
||||
The OS supports privilege separation (Ring 0 vs. Ring 3). When an application is launched, the kernel:
|
||||
|
||||
1. Loads the ELF file from the filesystem.
|
||||
2. Assigns the process to a CPU core via a round-robin distribution strategy.
|
||||
3. Allocates a new virtual address space (Page Directory) for the process.
|
||||
4. Maps the executable segments according to the ELF headers.
|
||||
5. Switches to User Mode (Ring 3) via the `iretq` instruction.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Programs interact with the core kernel using system calls (`syscall.c`). Multitasking is achieved by pre-empting user processes on their respective cores.
|
||||
|
||||
---
|
||||
37
docs/architecture/filesystem.md
Normal file
@@ -0,0 +1,37 @@
|
||||
<div align="center">
|
||||
<h1>Filesystem Architecture</h1>
|
||||
<p><em>Virtual File System layer and FAT32 abstraction in BoredOS.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
BoredOS implements a rudimentary but functional filesystem layer designed to support reading system assets and user applications during runtime.
|
||||
|
||||
## 🗂️ Virtual File System (VFS)
|
||||
|
||||
The Virtual File System acts as an abstraction layer across different underlying storage mechanisms (even if, currently, only one type is fully utilized). System calls targeting files (`SYS_FS`) route through the VFS rather than interacting with the disk directly.
|
||||
|
||||
Key VFS functionalities include:
|
||||
- **File Descriptors**: Mapping integer IDs to internal file structures for userland processes.
|
||||
- **Standard Operations**: Standardizing `open()`, `read()`, `write()`, `close()`, `seek()`, and directory listings.
|
||||
- **Path Parsing**: Resolving absolute and relative paths.
|
||||
- **SMP Safety**: All VFS and underlying FAT32 operations are protected by a global **Spinlock**. This ensures that multiple cores can safely read from the filesystem simultaneously without corrupting internal file seek pointers or directory cache states.
|
||||
|
||||
## 💾 FAT32 Implementation
|
||||
|
||||
The primary filesystem logic in `fat32.c` handles both in-memory RAM-based filesystem simulation and physical ATA block devices.
|
||||
|
||||
### 💿 Storage Support
|
||||
|
||||
BoredOS supports two main types of storage for its FAT32 implementation:
|
||||
|
||||
1. **RAMFS (Boot Modules)**: During boot, Limine loads necessary files (such as userland `.elf` binaries, fonts, and wallpapers) into memory as standard boot modules. The FAT32 code parses these loaded memory modules and automatically constructs a synthetic FAT32 directory tree inside RAM (mounted as `A:`).
|
||||
2. **ATA Drives**: The kernel includes a basic PIO-based ATA driver that can detect and read/write to physical IDE/PATA hard disks.
|
||||
- **GPT is NOT supported**: Currently, only **MBR (Master Boot Record)** partition tables or **raw (partitionless)** disks are supported.
|
||||
- **Filesystem**: The partition must be formatted as **FAT32**.
|
||||
|
||||
### 🔍 Auto-detection
|
||||
The `Disk Manager` automatically probes primary and secondary IDE channels during initialization. If a valid FAT32 partition is found (either directly at sector 0 or via an MBR partition table), the disk is assigned a drive letter (starting from `B:`) and becomes accessible to the VFS.
|
||||
|
||||
|
||||
---
|
||||
40
docs/architecture/memory.md
Normal file
@@ -0,0 +1,40 @@
|
||||
<div align="center">
|
||||
<h1>Memory Management</h1>
|
||||
<p><em>Physical and Virtual Memory coordination in x86_64 Long Mode.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
Memory management in BoredOS is split into physical and virtual layers, designed to support both kernel operations and userland isolation on the x86_64 architecture.
|
||||
|
||||
## 🧠 Physical Memory Management (PMM)
|
||||
|
||||
The PMM is responsible for tracking which physical RAM frames (usually 4KB each) are free and which are in use.
|
||||
|
||||
1. **Memory Map**: During boot, Limine provides a memory map detailing the available, reserved, and unusable physical memory regions.
|
||||
2. **Bitmap Allocator**: The core PMM uses a bitmap-based allocation strategy. Each bit in the bitmap represents a single physical page (frame). If a bit is `1`, the page is in use; if `0`, it is free.
|
||||
3. **Allocation**: When a new page is requested (e.g., for userland space or kernel heap), the PMM scans the bitmap for the first available zero bit, marks it as used, and returns the physical address.
|
||||
4. **SMP Safety**: In a multi-core environment, the PMM and VMM are protected by **Spinlocks** to prevent two CPUs from allocating the same frame or modifying page tables simultaneously.
|
||||
|
||||
> [!NOTE]
|
||||
> 4KB frame sizes strike a balance between allocation speed and minimal memory fragmentation, fitting directly with the page tables.
|
||||
|
||||
## 🗺️ Virtual Memory Management (VMM) and Paging
|
||||
|
||||
BoredOS uses 4-level paging (PML4), a requirement for x86_64 long mode, dividing the virtual address space between the kernel and userland.
|
||||
|
||||
- **Kernel Space**: The kernel relies on a higher-half design where its code, data, and heap are mapped to high addresses (typically above `0xFFFF800000000000`).
|
||||
- **Per-CPU Structures**: Each CPU core maintains its own architectural state in memory:
|
||||
* **Per-CPU GDT**: Each core is initialized with its own Global Descriptor Table.
|
||||
* **Per-CPU TSS**: Each core has a dedicated Task State Segment containing the `RSP0` pointer for its own kernel stack, ensuring safe interrupt handling across cores.
|
||||
- **User Space**: Userland applications are loaded into lower virtual addresses.
|
||||
- **Page Faults**: The `mem/` subsystem registers an Interrupt Service Routine (ISR) for page faults (Interrupt 14). If a process accesses unmapped memory, the handler determines whether to allocate a new frame or terminate the process.
|
||||
|
||||
## 🏗️ Kernel Heap
|
||||
|
||||
Dynamic allocation within the kernel (`kmalloc` and `kfree`) is layered on top of the physical allocator. The kernel maintains its own heap area in virtual memory. When the heap requires more space, it requests physical frames from the PMM and maps them into the kernel's virtual address space.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The kernel heap is a shared resource; therefore, all `kmalloc` and `kfree` operations are guarded by a global spinlock to ensure thread safety during multi-core execution.
|
||||
|
||||
---
|
||||
48
docs/architecture/window_manager.md
Normal file
@@ -0,0 +1,48 @@
|
||||
<div align="center">
|
||||
<h1>Window Manager (WM)</h1>
|
||||
<p><em>The native graphical subsystem compositing and event routing.</em></p>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
BoredOS features a fully custom, graphical Window Manager built directly into the kernel, residing in the `src/wm/` directory. It is responsible for compositing the screen, handling window logic, rendering text, and dispatching UI events.
|
||||
|
||||
## 🖼️ Framebuffer and Rendering
|
||||
|
||||
1. **Limine Framebuffer**: During boot, the Limine bootloader requests a graphical framebuffer from the hardware (e.g., GOP in UEFI environments) and passes a pointer to this linear memory buffer to the kernel.
|
||||
2. **Double Buffering**: To prevent screen tearing, the WM does not draw directly to the screen. It allocates a "back buffer" in kernel memory equal to the size of the screen. All drawing operations (lines, rectangles, windows) happen on this back buffer.
|
||||
3. **Compositing**: Once per frame or upon request, the entire back buffer (or dirty regions) is copied to the actual Limine physical framebuffer memory, making the changes visible instantly.
|
||||
|
||||
> [!TIP]
|
||||
> The performance of the window manager heavily depends on minimizing the "dirty regions" drawn in the compositing loop rather than sweeping the whole screen.
|
||||
|
||||
## 🪟 Window System (`wm.c`)
|
||||
|
||||
The windowing system is built around a linked list of `Window` structures.
|
||||
|
||||
- **Z-Ordering**: The list determines the draw order. Windows at the back of the list are drawn first, and the active window is drawn last (on top).
|
||||
- **Window Structures**: Each window object tracks its dimensions (`x`, `y`, `width`, `height`), title, background color, and an internal buffer if it's acting as a canvas for userland apps.
|
||||
- **Decorations**: The kernel handles drawing window borders, title bars, and close buttons automatically unless a borderless style is specified.
|
||||
|
||||
## 🖱️ Input Handling and Events
|
||||
|
||||
The WM acts as the central hub for input routing.
|
||||
|
||||
1. **Mouse Driver**: The PS/2 mouse driver (`dev/mouse.c`) detects movement and button clicks. It raises interrupts that update global cursor coordinates.
|
||||
2. **Hit Testing**: The WM checks these coordinates against the bounding boxes of existing windows. It handles dragging logic (if the user clicks a title bar) or focus changes.
|
||||
3. **Event Queue**: If a userland application owns the window that was clicked, the WM packages the input (coordinates, button state) into an event message and drops it into the owning process's event queue. The application can retrieve these via the custom libc UI functions.
|
||||
|
||||
- **Event Polling**: The UI loop inside an app continuously calls `ui_poll_event()` to respond to mouse clicks and window movement dispatched by the kernel WM.
|
||||
|
||||
## 🧵 Multi-Core Safety & Performance
|
||||
|
||||
With the introduction of Symmetric Multi-Processing (SMP), the Window Manager (WM) was redesigned to ensure stability and high performance across multiple cores.
|
||||
|
||||
1. **Granular Window Locks**: Each `Window` object possesses its own `spinlock_t lock;`. User applications concurrently draw directly into their own window buffers without stalling the rest of the system. The global `wm_lock` is reserved strictly for altering global structures like window z-order or syncing buffers to the screen compositing layer.
|
||||
2. **Per-CPU Rendering State**: To facilitate simultaneous GUI system calls across all CPU cores, the low-level rendering context (`g_render_target` array) is isolated per-CPU using the core ID. This allows completely lockless multi-core pixel rasterization, drastically reducing rendering bottlenecks.
|
||||
3. **Deferred Compositing**: Final screen composition (`wm_paint`) is scheduled to the main kernel idle loop on the Bootstrap Processor (BSP). This enables application cores to continue processing logic seamlessly while the GUI asynchronously handles flipping the physical framebuffer.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Because application rendering (rasterizing geometry into a window's backbuffer) is SMP-safe and lock-free across cores, GUI performance scales linearly with the number of CPUs active.
|
||||
|
||||
---
|
||||
52
docs/build/toolchain.md
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# Build Toolchain
|
||||
|
||||
BoredOS is built cross-compiled from a host system (such as macOS or Linux) to target the generic `x86_64-elf` platform.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To build BoredOS, you need the following tools:
|
||||
|
||||
1. **x86_64 ELF GCC Cross-Compiler**:
|
||||
- `x86_64-elf-gcc`: The C compiler targeting the freestanding overarching ELF environment.
|
||||
- `x86_64-elf-ld`: The linker to combine object files into the final `boredos.elf` kernel binary and userland variables.
|
||||
|
||||
2. **NASM**:
|
||||
- Required to compile the `.asm` files in `src/arch/` and `src/userland/crt0.asm`. It formats the output as `elf64` objects to be linked alongside the C code.
|
||||
|
||||
3. **xorriso**:
|
||||
- A specialized tool to create ISO 9660 filesystem images.
|
||||
- *Why?* `xorriso` packages the compiled kernel, Limine bootloader, and asset files (fonts, images, userland binaries) into the final bootable `boredos.iso` CD-ROM image.
|
||||
|
||||
4. **QEMU** (Optional but highly recommended for testing):
|
||||
- `qemu-system-x86_64` is used for rapid emulation and testing.
|
||||
|
||||
## Installation (macOS)
|
||||
|
||||
You can easily install the complete toolchain using Homebrew:
|
||||
|
||||
```sh
|
||||
brew install x86_64-elf-binutils x86_64-elf-gcc nasm xorriso qemu
|
||||
```
|
||||
|
||||
## Installation (Linux)
|
||||
|
||||
Depending on your distribution, the installation commands vary. Note that some distributions may require you to build the `x86_64-elf` cross-compiler from source if it isn't available in their default repositories.
|
||||
|
||||
### Debian / Ubuntu
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt install build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo nasm xorriso qemu-system-x86
|
||||
```
|
||||
*(Note: You will need to build the `x86_64-elf` cross-compiler from source or find a compatible PPA, as it is not in the default Debian/Ubuntu repositories.)*
|
||||
|
||||
### Arch Linux
|
||||
Arch Linux provides the regular tools in its standard repositories and the cross-compiler via the AUR:
|
||||
```sh
|
||||
sudo pacman -S nasm xorriso qemu-full
|
||||
yay -S x86_64-elf-gcc x86_64-elf-binutils
|
||||
```
|
||||
|
||||
### Fedora
|
||||
```sh
|
||||
sudo dnf install make gcc gcc-c++ bison flex gmp-devel mpfr-devel libmpc-devel texinfo nasm xorriso qemu
|
||||
```
|
||||
58
docs/build/usage.md
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
# Building, Running, and Deployment
|
||||
|
||||
BoredOS uses a single top-level `Makefile` to orchestrate the build process.
|
||||
|
||||
## The Build Process
|
||||
|
||||
When you run `make` in the root directory, the following stages occur automatically:
|
||||
|
||||
1. **Limine Setup (`limine-setup`)**:
|
||||
If the Limine bootloader binaries are missing, the Makefile automatically clones the appropriate Limine binary release from GitHub and compiles its host utility.
|
||||
2. **Kernel Compilation**:
|
||||
All `.c` files in `src/core`, `src/mem`, `src/dev`, `src/sys`, `src/fs`, `src/wm`, and `src/net` are compiled into object files (`.o`) inside the `build/` directory using `x86_64-elf-gcc`.
|
||||
3. **Kernel Assembly**:
|
||||
All `.asm` files in `src/arch/` are assembled into object files using `nasm`.
|
||||
4. **Kernel Linking**:
|
||||
`x86_64-elf-ld` links the kernel object files together, instructed by the `linker.ld` script, outputting the `boredos.elf` kernel binary.
|
||||
5. **Userland Compilation**:
|
||||
The Makefile shifts into the `src/userland` directory, compiling the custom `libc` and generating `bin/*.elf` executable user applications.
|
||||
6. **ISO Generation**:
|
||||
The `iso_root` directory is staged. The kernel, Limine configuration, fonts, images, and userland applications are copied in. Finally, `xorriso` generates the `boredos.iso` bootable image.
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
To run BoredOS successfully (either in emulation or on bare metal), your target machine should meet the following minimum requirements:
|
||||
|
||||
- **CPU**: An `x86_64` (64-bit) compatible processor.
|
||||
- **Memory**: Approximately `~256 MB` of RAM.
|
||||
- **Display**: A VGA-compatible display (required for the GUI Window Manager).
|
||||
- **Networking (Optional)**: A compatible Network Interface Card (NIC) is required if you want to use the networking stack (e.g., an Intel E1000 or similar supported by the [`net/nic/`](../../src/net/nic/) drivers). Networking is not strictly required for the OS to boot or run offline applications.
|
||||
|
||||
|
||||
## Running in Emulation
|
||||
|
||||
To test the generated ISO quickly without real hardware, use the QEMU emulator:
|
||||
|
||||
```sh
|
||||
make run
|
||||
```
|
||||
|
||||
This command invokes QEMU with specific arguments:
|
||||
- `-m 4G`: Allocates 4 Gigabytes of RAM.
|
||||
- `-cdrom boredos.iso`: Mounts the built OS image as a CD-ROM.
|
||||
- `-netdev user...`: Sets up a basic NAT network interface for the OS's networking stack.
|
||||
- `-smp 4`: Enables 4 CPU cores.
|
||||
- `-drive file=disk.img...`: Attaches a raw disk image included in this release of BoredOS.
|
||||
|
||||
## Running on Bare Metal
|
||||
|
||||
> [!CAUTION]
|
||||
> Running hobby operating systems on real hardware is at your own risk and may cause undefined behavior.
|
||||
|
||||
To boot BoredOS on a physical PC:
|
||||
|
||||
1. Build the OS to get `boredos.iso`.
|
||||
2. Use a flashing tool like **Balena Etcher** or `dd` to write the ISO to a USB flash drive.
|
||||
3. Reboot your target computer, enter the BIOS/UEFI setup.
|
||||
4. **Boot Configuration**: BoredOS supports booting on both modern **UEFI** systems and legacy **BIOS** systems natively via Limine. Ensure **Secure Boot** is disabled in your firmware settings.
|
||||
5. Select the USB drive from the boot menu.
|
||||
1
limine
BIN
screenshot.jpg
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 342 KiB |
BIN
src/.DS_Store
vendored
@@ -7,9 +7,13 @@ global isr1_wrapper
|
||||
global isr8_wrapper
|
||||
global isr12_wrapper
|
||||
global isr14_wrapper
|
||||
global isr128_wrapper
|
||||
global isr_sched_ipi_wrapper
|
||||
extern timer_handler
|
||||
extern keyboard_handler
|
||||
extern mouse_handler
|
||||
extern sched_ipi_handler
|
||||
extern syscall_handler_c
|
||||
extern exception_handler_c
|
||||
|
||||
; Helper to send EOI (End of Interrupt) to PIC
|
||||
@@ -41,7 +45,7 @@ isr%2_wrapper:
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; Save SSE/FPU state
|
||||
; Save SSE/FPU state (fxsave requires 16-byte alignment)
|
||||
sub rsp, 512
|
||||
fxsave [rsp]
|
||||
|
||||
@@ -85,6 +89,12 @@ isr1_wrapper:
|
||||
isr12_wrapper:
|
||||
ISR_NOERRCODE mouse_handler, 44
|
||||
|
||||
isr_sched_ipi_wrapper:
|
||||
ISR_NOERRCODE sched_ipi_handler, 65
|
||||
|
||||
isr128_wrapper:
|
||||
ISR_NOERRCODE syscall_handler_c, 128
|
||||
|
||||
; Common exception macro for exceptions WITHOUT error code
|
||||
%macro EXCEPTION_NOERRCODE 1
|
||||
global exc%1_wrapper
|
||||
@@ -154,7 +164,7 @@ exception_common:
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; Save SSE/FPU state
|
||||
; Save SSE/FPU state (fxsave requires 16-byte alignment)
|
||||
sub rsp, 512
|
||||
fxsave [rsp]
|
||||
|
||||
@@ -108,17 +108,40 @@ void k_reboot(void) {
|
||||
}
|
||||
|
||||
void k_shutdown(void) {
|
||||
outw(0x604, 0x2000);
|
||||
outw(0xB004, 0x2000); // QEMU older / some pc machines
|
||||
outw(0x604, 0x2000); // QEMU newer (i440fx/q35)
|
||||
outw(0x4004, 0x3400); // VirtualBox fallback
|
||||
}
|
||||
|
||||
volatile uint64_t beep_end_tick = 0;
|
||||
bool beep_active = false;
|
||||
|
||||
void k_beep(int freq, int ms) {
|
||||
if (freq <= 0) return;
|
||||
if (freq <= 0) {
|
||||
outb(0x61, inb(0x61) & 0xFC);
|
||||
beep_active = false;
|
||||
return;
|
||||
}
|
||||
int div = 1193180 / freq;
|
||||
outb(0x43, 0xB6);
|
||||
outb(0x42, div & 0xFF);
|
||||
outb(0x42, (div >> 8) & 0xFF);
|
||||
outb(0x61, inb(0x61) | 0x03);
|
||||
k_sleep(ms);
|
||||
outb(0x61, inb(0x61) & 0xFC);
|
||||
|
||||
uint32_t ticks = ms / 16;
|
||||
if (ticks == 0 && ms > 0) ticks = 1;
|
||||
extern volatile uint64_t kernel_ticks;
|
||||
beep_end_tick = kernel_ticks + ticks;
|
||||
beep_active = true;
|
||||
}
|
||||
|
||||
void k_beep_process(void) {
|
||||
if (beep_active) {
|
||||
extern volatile uint64_t kernel_ticks;
|
||||
if (kernel_ticks >= beep_end_tick) {
|
||||
outb(0x61, inb(0x61) & 0xFC);
|
||||
beep_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Kernel string utilities
|
||||
void k_memset(void *dest, int val, size_t len);
|
||||
@@ -23,5 +24,6 @@ void k_sleep(int ms);
|
||||
void k_reboot(void);
|
||||
void k_shutdown(void);
|
||||
void k_beep(int freq, int ms);
|
||||
void k_beep_process(void);
|
||||
|
||||
#endif
|
||||
@@ -16,9 +16,13 @@
|
||||
#include "wm.h"
|
||||
#include "io.h"
|
||||
#include "fat32.h"
|
||||
#include "tar.h"
|
||||
#include "memory_manager.h"
|
||||
#include "platform.h"
|
||||
#include "wallpaper.h"
|
||||
#include "smp.h"
|
||||
#include "work_queue.h"
|
||||
#include "lapic.h"
|
||||
|
||||
// --- Limine Requests ---
|
||||
__attribute__((used, section(".requests")))
|
||||
@@ -42,11 +46,19 @@ static volatile struct limine_module_request module_request = {
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".requests")))
|
||||
static volatile struct limine_smp_request smp_request = {
|
||||
.id = LIMINE_SMP_REQUEST,
|
||||
.revision = 0,
|
||||
.flags = 0
|
||||
};
|
||||
|
||||
__attribute__((used, section(".requests_start")))
|
||||
static volatile struct limine_request *const requests_start_marker[] = {
|
||||
(struct limine_request *)&framebuffer_request,
|
||||
(struct limine_request *)&memmap_request,
|
||||
(struct limine_request *)&module_request,
|
||||
(struct limine_request *)&smp_request,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -93,6 +105,32 @@ void serial_write_hex(uint64_t n) {
|
||||
}
|
||||
|
||||
// Kernel Entry Point
|
||||
|
||||
static void fat32_mkdir_recursive(const char *path) {
|
||||
char temp[256];
|
||||
int i = 0;
|
||||
|
||||
// Skip initial slash
|
||||
if (path[0] == '/') {
|
||||
temp[0] = '/';
|
||||
i = 1;
|
||||
}
|
||||
|
||||
while (path[i] && i < 255) {
|
||||
temp[i] = path[i];
|
||||
if (path[i] == '/') {
|
||||
temp[i] = '\0';
|
||||
fat32_mkdir(temp);
|
||||
temp[i] = '/';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i > 0 && temp[i-1] != '/') {
|
||||
temp[i] = '\0';
|
||||
fat32_mkdir(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void kmain(void) {
|
||||
init_serial();
|
||||
serial_write("\n[DEBUG] Entering kmain...\n");
|
||||
@@ -158,6 +196,7 @@ void kmain(void) {
|
||||
fat32_mkdir("/Library/images/gif");
|
||||
fat32_mkdir("/Library/Fonts");
|
||||
fat32_mkdir("/Library/DOOM");
|
||||
fat32_mkdir("/docs");
|
||||
|
||||
if (module_request.response == NULL) {
|
||||
serial_write("[DEBUG] ERROR: Limine Module Response is NULL!\n");
|
||||
@@ -172,6 +211,26 @@ void kmain(void) {
|
||||
if (fs_starts_with(clean_path, "boot():")) clean_path += 7;
|
||||
else if (fs_starts_with(clean_path, "boot:///")) clean_path += 8;
|
||||
|
||||
int len = 0;
|
||||
while(clean_path[len]) len++;
|
||||
|
||||
if (len >= 4 && clean_path[len-4] == '.' && clean_path[len-3] == 't' && clean_path[len-2] == 'a' && clean_path[len-1] == 'r') {
|
||||
serial_write("[DEBUG] Parsing TAR initrd: ");
|
||||
serial_write(clean_path);
|
||||
serial_write("\n");
|
||||
tar_parse(mod->address, mod->size);
|
||||
} else {
|
||||
char dir_path[256];
|
||||
int last_slash = -1;
|
||||
for (int j = 0; clean_path[j]; j++) {
|
||||
if (clean_path[j] == '/') last_slash = j;
|
||||
}
|
||||
if (last_slash > 0) {
|
||||
for (int j = 0; j < last_slash; j++) dir_path[j] = clean_path[j];
|
||||
dir_path[last_slash] = '\0';
|
||||
fat32_mkdir_recursive(dir_path);
|
||||
}
|
||||
|
||||
FAT32_FileHandle *fh = fat32_open(clean_path, "w");
|
||||
if (fh && fh->valid) {
|
||||
fat32_write(fh, mod->address, mod->size);
|
||||
@@ -179,6 +238,7 @@ void kmain(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize fonts now that FAT32 and modules are loaded
|
||||
uint64_t current_rsp;
|
||||
@@ -193,11 +253,25 @@ void kmain(void) {
|
||||
ps2_init();
|
||||
asm("sti");
|
||||
|
||||
// Initialize LAPIC for IPI support
|
||||
lapic_init();
|
||||
|
||||
// Initialize SMP — bring up all CPU cores
|
||||
if (smp_request.response != NULL) {
|
||||
uint32_t online = smp_init(smp_request.response);
|
||||
serial_write("[DEBUG] SMP init complete, CPUs online: ");
|
||||
serial_write_num(online);
|
||||
serial_write("\n");
|
||||
} else {
|
||||
serial_write("[DEBUG] No SMP response from bootloader\n");
|
||||
// Still init as single-CPU
|
||||
smp_init(NULL);
|
||||
}
|
||||
|
||||
wm_init();
|
||||
|
||||
asm volatile("sti");
|
||||
|
||||
|
||||
while (1) {
|
||||
wm_process_input();
|
||||
wm_process_deferred_thumbs();
|
||||
33
src/core/version.c
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "syscall.h"
|
||||
#include <stddef.h>
|
||||
|
||||
extern void mem_memcpy(void *dest, const void *src, size_t len);
|
||||
|
||||
void get_os_info(os_info_t *info) {
|
||||
if (!info) return;
|
||||
|
||||
char *p = (char *)info;
|
||||
for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0;
|
||||
|
||||
const char *os_name = "BoredOS";
|
||||
const char *os_version = "26.4";
|
||||
const char *os_codename = "Geometry";
|
||||
const char *kernel_name = "Boredkernel";
|
||||
const char *kernel_version = "3.2.3";
|
||||
const char *build_date = __DATE__;
|
||||
const char *build_time = __TIME__;
|
||||
const char *build_arch = "x86_64";
|
||||
|
||||
int j;
|
||||
j = 0; while (os_name[j] && j < 63) { info->os_name[j] = os_name[j]; j++; } info->os_name[j] = '\0';
|
||||
j = 0; while (os_version[j] && j < 63) { info->os_version[j] = os_version[j]; j++; } info->os_version[j] = '\0';
|
||||
j = 0; while (os_codename[j] && j < 63) { info->os_codename[j] = os_codename[j]; j++; } info->os_codename[j] = '\0';
|
||||
j = 0; while (kernel_name[j] && j < 63) { info->kernel_name[j] = kernel_name[j]; j++; } info->kernel_name[j] = '\0';
|
||||
j = 0; while (kernel_version[j] && j < 63) { info->kernel_version[j] = kernel_version[j]; j++; } info->kernel_version[j] = '\0';
|
||||
j = 0; while (build_date[j] && j < 63) { info->build_date[j] = build_date[j]; j++; } info->build_date[j] = '\0';
|
||||
j = 0; while (build_time[j] && j < 63) { info->build_time[j] = build_time[j]; j++; } info->build_time[j] = '\0';
|
||||
j = 0; while (build_arch[j] && j < 63) { info->build_arch[j] = build_arch[j]; j++; } info->build_arch[j] = '\0';
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "io.h"
|
||||
#include "wm.h"
|
||||
#include "network.h"
|
||||
#include "lapic.h"
|
||||
#include "smp.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
extern void serial_print(const char *s);
|
||||
@@ -18,9 +20,19 @@ uint64_t timer_handler(registers_t *regs) {
|
||||
wm_timer_tick();
|
||||
network_process_frames();
|
||||
|
||||
extern void k_beep_process(void);
|
||||
k_beep_process();
|
||||
|
||||
outb(0x20, 0x20); // EOI after processing to prevent nested timer interrupts
|
||||
extern uint64_t process_schedule(uint64_t current_rsp);
|
||||
return process_schedule((uint64_t)regs);
|
||||
uint64_t new_rsp = process_schedule((uint64_t)regs);
|
||||
|
||||
// SMP: Wake AP cores to run their assigned processes
|
||||
if (smp_cpu_count() > 1) {
|
||||
lapic_send_ipi_all();
|
||||
}
|
||||
|
||||
return new_rsp;
|
||||
}
|
||||
|
||||
// --- Keyboard ---
|
||||
BIN
src/fonts/Emoji/NotoEmoji-VariableFont_wght.ttf
Normal file
@@ -8,6 +8,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "wm.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
// Global lock for FAT32 operations (SMP safety)
|
||||
static spinlock_t fat32_lock = SPINLOCK_INIT;
|
||||
|
||||
|
||||
#define MAX_FILES 256
|
||||
@@ -228,6 +232,16 @@ static uint32_t ramfs_allocate_cluster(void) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
static int ramfs_count_files_in_dir(const char *normalized_path) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (files[i].used && fs_strcmp(files[i].parent_path, normalized_path) == 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool check_desktop_limit(const char *normalized_path) {
|
||||
if (desktop_file_limit < 0) return true;
|
||||
if (fs_strlen(normalized_path) > 9 &&
|
||||
@@ -241,10 +255,8 @@ static bool check_desktop_limit(const char *normalized_path) {
|
||||
if (*p == '/') return true;
|
||||
p++;
|
||||
}
|
||||
FAT32_FileInfo *info = (FAT32_FileInfo*)kmalloc(256 * sizeof(FAT32_FileInfo));
|
||||
if (!info) return true;
|
||||
int count = fat32_list_directory("/Desktop", info, 256);
|
||||
kfree(info);
|
||||
|
||||
int count = ramfs_count_files_in_dir("/Desktop");
|
||||
if (count >= desktop_file_limit) return false;
|
||||
}
|
||||
return true;
|
||||
@@ -1218,8 +1230,8 @@ char fat32_get_current_drive(void) {
|
||||
}
|
||||
|
||||
FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1234,13 +1246,13 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
|
||||
handle = realfs_open(drive, p, mode);
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return handle;
|
||||
}
|
||||
|
||||
void fat32_close(FAT32_FileHandle *handle) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
if (handle && handle->valid) {
|
||||
if (handle->drive != 'A' && handle->mode != 0) { // Both read and write modes for real drives
|
||||
Disk *d = disk_get_by_letter(handle->drive);
|
||||
@@ -1265,14 +1277,14 @@ void fat32_close(FAT32_FileHandle *handle) {
|
||||
}
|
||||
handle->valid = false;
|
||||
}
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
}
|
||||
|
||||
int fat32_read(FAT32_FileHandle *handle, void *buffer, int size) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
if (!handle || !handle->valid || handle->mode != 0) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1283,15 +1295,15 @@ int fat32_read(FAT32_FileHandle *handle, void *buffer, int size) {
|
||||
ret = realfs_read(handle, buffer, size);
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
if (!handle || !handle->valid || (handle->mode != 1 && handle->mode != 2)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1302,15 +1314,15 @@ int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
|
||||
ret = realfs_write(handle, buffer, size);
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fat32_seek(FAT32_FileHandle *handle, int offset, int whence) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
if (!handle || !handle->valid) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1349,7 +1361,7 @@ int fat32_seek(FAT32_FileHandle *handle, int offset, int whence) {
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return new_position;
|
||||
}
|
||||
|
||||
@@ -1487,13 +1499,13 @@ bool fat32_mkdir(const char *path) {
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
if (drive != 'A') {
|
||||
bool res = realfs_mkdir(drive, p);
|
||||
wm_notify_fs_change();
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1501,18 +1513,18 @@ bool fat32_mkdir(const char *path) {
|
||||
fat32_normalize_path(p, normalized);
|
||||
|
||||
if (ramfs_find_file(normalized)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_desktop_limit(normalized)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
FileEntry *entry = ramfs_find_free_entry();
|
||||
if (!entry) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1525,33 +1537,33 @@ bool fat32_mkdir(const char *path) {
|
||||
entry->attributes = ATTR_DIRECTORY;
|
||||
|
||||
wm_notify_fs_change();
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fat32_rmdir(const char *path) {
|
||||
if (parse_drive_from_path(&path) != 'A') return false;
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
char normalized[FAT32_MAX_PATH];
|
||||
fat32_normalize_path(path, normalized);
|
||||
|
||||
FileEntry *entry = ramfs_find_file(normalized);
|
||||
if (!entry || !(entry->attributes & ATTR_DIRECTORY)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
entry->used = false;
|
||||
wm_notify_fs_change();
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fat32_delete(const char *path) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1565,7 +1577,7 @@ bool fat32_delete(const char *path) {
|
||||
|
||||
FileEntry *entry = ramfs_find_file(normalized);
|
||||
if (!entry || (entry->attributes & ATTR_DIRECTORY)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1577,13 +1589,13 @@ bool fat32_delete(const char *path) {
|
||||
result = realfs_delete(drive, p);
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return result;
|
||||
}
|
||||
|
||||
int fat32_get_info(const char *path, FAT32_FileInfo *info) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1619,13 +1631,13 @@ int fat32_get_info(const char *path, FAT32_FileInfo *info) {
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool fat32_exists(const char *path) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1644,7 +1656,7 @@ bool fat32_exists(const char *path) {
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return exists;
|
||||
}
|
||||
|
||||
@@ -1653,13 +1665,13 @@ bool fat32_rename(const char *old_path, const char *new_path) {
|
||||
if (parse_drive_from_path(&old_path) != 'A') return false;
|
||||
if (parse_drive_from_path(&new_path) != 'A') return false;
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
FileEntry *entry = ramfs_find_file(old_path); // Need to normalize inside find? yes ramfs_find calls normalize
|
||||
if (!entry) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; }
|
||||
if (!entry) { spinlock_release_irqrestore(&fat32_lock, rflags); return false; }
|
||||
|
||||
// Check destination
|
||||
if (ramfs_find_file(new_path)) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; }
|
||||
if (ramfs_find_file(new_path)) { spinlock_release_irqrestore(&fat32_lock, rflags); return false; }
|
||||
|
||||
size_t old_len = fs_strlen(old_path);
|
||||
// Logic from original rename...
|
||||
@@ -1689,13 +1701,13 @@ bool fat32_rename(const char *old_path, const char *new_path) {
|
||||
}
|
||||
}
|
||||
wm_notify_fs_change();
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fat32_is_directory(const char *path) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1718,13 +1730,13 @@ bool fat32_is_directory(const char *path) {
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return is_dir;
|
||||
}
|
||||
|
||||
int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entries) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1749,13 +1761,13 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
|
||||
count = realfs_list_directory(drive, p, entries, max_entries);
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return count;
|
||||
}
|
||||
|
||||
bool fat32_chdir(const char *path) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
@@ -1767,11 +1779,11 @@ bool fat32_chdir(const char *path) {
|
||||
current_dir[1] = 0;
|
||||
// If just switching drive (e.g. "B:"), return true
|
||||
if (p[0] == 0) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1787,17 +1799,17 @@ bool fat32_chdir(const char *path) {
|
||||
|
||||
}
|
||||
}
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return true;
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
return false;
|
||||
}
|
||||
|
||||
void fat32_get_current_dir(char *buffer, int size) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
// SMP: Use FAT32 spinlock
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&fat32_lock);
|
||||
|
||||
int len = 0;
|
||||
buffer[0] = current_drive;
|
||||
@@ -1811,5 +1823,5 @@ void fat32_get_current_dir(char *buffer, int size) {
|
||||
buffer[len + i] = current_dir[i];
|
||||
}
|
||||
buffer[len + dir_len] = 0;
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&fat32_lock, rflags);
|
||||
}
|
||||
128
src/fs/tar.c
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "tar.h"
|
||||
#include "fat32.h"
|
||||
|
||||
// The standard TAR header block is 512 bytes.
|
||||
struct tar_header {
|
||||
char filename[100];
|
||||
char mode[8];
|
||||
char uid[8];
|
||||
char gid[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char chksum[8];
|
||||
char typeflag;
|
||||
char linkname[100];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char uname[32];
|
||||
char gname[32];
|
||||
char devmajor[8];
|
||||
char devminor[8];
|
||||
char prefix[155];
|
||||
char pad[12];
|
||||
} __attribute__((packed));
|
||||
|
||||
// Helper: parse tar octal field representation
|
||||
static uint64_t tar_parse_octal(const char *str, int size) {
|
||||
uint64_t result = 0;
|
||||
while (size-- > 0) {
|
||||
if (*str >= '0' && *str <= '7') {
|
||||
result = (result << 3) + (*str - '0');
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper: Make directories sequentially for nested paths
|
||||
static void tar_mkdir_recursive(const char *path) {
|
||||
char temp[256];
|
||||
int i = 0;
|
||||
if (path[0] == '/') {
|
||||
temp[0] = '/';
|
||||
i = 1;
|
||||
}
|
||||
while (path[i] && i < 255) {
|
||||
temp[i] = path[i];
|
||||
if (path[i] == '/') {
|
||||
temp[i] = '\0';
|
||||
fat32_mkdir(temp);
|
||||
temp[i] = '/';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i > 0 && temp[i - 1] != '/') {
|
||||
temp[i] = '\0';
|
||||
fat32_mkdir(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void tar_parse(void *archive, uint64_t archive_size) {
|
||||
uint8_t *ptr = (uint8_t *)archive;
|
||||
uint8_t *end = ptr + archive_size;
|
||||
|
||||
while (ptr + 512 <= end) {
|
||||
struct tar_header *header = (struct tar_header *)ptr;
|
||||
|
||||
// End of archive is marked by empty blocks
|
||||
if (header->filename[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t file_size = tar_parse_octal(header->size, 11);
|
||||
|
||||
char full_path[256];
|
||||
// Ensure path starts with a '/' for VFS consistency
|
||||
if (header->filename[0] != '/') {
|
||||
full_path[0] = '/';
|
||||
int j = 0;
|
||||
while (header->filename[j] && j < 254) {
|
||||
full_path[j + 1] = header->filename[j];
|
||||
j++;
|
||||
}
|
||||
full_path[j + 1] = '\0';
|
||||
} else {
|
||||
int j = 0;
|
||||
while (header->filename[j] && j < 255) {
|
||||
full_path[j] = header->filename[j];
|
||||
j++;
|
||||
}
|
||||
full_path[j] = '\0';
|
||||
}
|
||||
|
||||
if (header->typeflag == '5') {
|
||||
// It's a directory
|
||||
tar_mkdir_recursive(full_path);
|
||||
} else if (header->typeflag == '0' || header->typeflag == '\0') {
|
||||
// It's a normal file
|
||||
// First ensure the parent directory exists
|
||||
char parent_path[256];
|
||||
int last_slash = -1;
|
||||
for (int j = 0; full_path[j]; j++) {
|
||||
parent_path[j] = full_path[j];
|
||||
if (full_path[j] == '/') {
|
||||
last_slash = j;
|
||||
}
|
||||
}
|
||||
if (last_slash > 0) {
|
||||
parent_path[last_slash] = '\0';
|
||||
tar_mkdir_recursive(parent_path);
|
||||
}
|
||||
|
||||
// Extract the file data block directly into the VFS
|
||||
FAT32_FileHandle *fh = fat32_open(full_path, "w");
|
||||
if (fh && fh->valid) {
|
||||
fat32_write(fh, ptr + 512, file_size);
|
||||
fat32_close(fh);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance pointer to the next file header
|
||||
// Header block (512) + File data (padded to 512-byte multiples)
|
||||
uint64_t data_blocks = (file_size + 511) / 512;
|
||||
ptr += 512 + (data_blocks * 512);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#ifndef LICENSEWR_H
|
||||
#define LICENSEWR_H
|
||||
#ifndef TAR_H
|
||||
#define TAR_H
|
||||
|
||||
void write_license_file(void);
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Parse a TAR archive located in memory and extract its contents into the current filesystem (fatal32 RAM disk).
|
||||
void tar_parse(void *archive, uint64_t archive_size);
|
||||
|
||||
#endif
|
||||
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 4.2 MiB After Width: | Height: | Size: 4.2 MiB |
|
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 600 KiB After Width: | Height: | Size: 600 KiB |
|
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
BIN
src/kernel/.DS_Store
vendored
@@ -1,9 +0,0 @@
|
||||
#ifndef E1000_NETIF_H
|
||||
#define E1000_NETIF_H
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t e1000_netif_init(struct netif *netif);
|
||||
void e1000_netif_poll(struct netif *netif);
|
||||
|
||||
#endif
|
||||
@@ -1,227 +0,0 @@
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "memory_manager.h"
|
||||
#include "font_manager.h"
|
||||
#include "stb_truetype.h"
|
||||
#include "fat32.h"
|
||||
#include <stddef.h>
|
||||
|
||||
// Simple math implementations for stb_truetype
|
||||
float ksqrtf(float x) {
|
||||
float res;
|
||||
asm volatile("sqrtss %1, %0" : "=x"(res) : "x"(x));
|
||||
return res;
|
||||
}
|
||||
|
||||
float kfabsf(float x) {
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
|
||||
float kpowf(float b, float e) {
|
||||
// Very simplified pow for stb_truetype's needs
|
||||
if (e == 0) return 1.0f;
|
||||
if (e == 1) return b;
|
||||
if (e == 0.5f) return ksqrtf(b);
|
||||
|
||||
// Fallback/log-based would be complex, let's see if this suffices
|
||||
float res = 1.0f;
|
||||
for (int i = 0; i < (int)e; i++) res *= b;
|
||||
return res;
|
||||
}
|
||||
|
||||
float kfmodf(float x, float y) {
|
||||
return x - (int)(x / y) * y;
|
||||
}
|
||||
|
||||
float kcosf(float x) {
|
||||
// Taylor series for cos(x) around 0
|
||||
float x2 = x * x;
|
||||
return 1.0f - (x2 / 2.0f) + (x2 * x2 / 24.0f) - (x2 * x2 * x2 / 720.0f);
|
||||
}
|
||||
|
||||
float kacosf(float x) {
|
||||
// Very rough approximation for acos(x)
|
||||
if (x >= 1.0f) return 0;
|
||||
if (x <= -1.0f) return 3.14159f;
|
||||
return 1.57079f - x - (x*x*x)/6.0f;
|
||||
}
|
||||
|
||||
extern void serial_write(const char *s);
|
||||
extern uint32_t graphics_get_pixel(int x, int y);
|
||||
|
||||
static inline uint32_t alpha_blend(uint32_t bg, uint32_t fg, uint8_t alpha) {
|
||||
if (alpha == 0) return bg;
|
||||
if (alpha == 255) return fg;
|
||||
|
||||
uint32_t rb = (((fg & 0xFF00FF) * alpha) + ((bg & 0xFF00FF) * (255 - alpha))) >> 8;
|
||||
uint32_t g = (((fg & 0x00FF00) * alpha) + ((bg & 0x00FF00) * (255 - alpha))) >> 8;
|
||||
return (rb & 0xFF00FF) | (g & 0x00FF00);
|
||||
}
|
||||
|
||||
static ttf_font_t *default_font = NULL;
|
||||
|
||||
#define FONT_CACHE_SIZE 2048
|
||||
typedef struct {
|
||||
char c;
|
||||
float pixel_height;
|
||||
int w, h, xoff, yoff;
|
||||
unsigned char *bitmap;
|
||||
} font_cache_entry_t;
|
||||
|
||||
// Cache is disabled for now due to race conditions and collisions
|
||||
// static font_cache_entry_t g_font_cache[FONT_CACHE_SIZE];
|
||||
|
||||
bool font_manager_init(void) {
|
||||
// We'll load a default font later if available
|
||||
return true;
|
||||
}
|
||||
|
||||
ttf_font_t* font_manager_load(const char *path, float size) {
|
||||
FAT32_FileHandle *fh = fat32_open(path, "r");
|
||||
if (!fh || !fh->valid) {
|
||||
serial_write("[FONT] Failed to open font file: ");
|
||||
serial_write(path);
|
||||
serial_write("\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t fsize = fh->size;
|
||||
unsigned char *buffer = kmalloc(fsize);
|
||||
if (!buffer) {
|
||||
fat32_close(fh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int read = fat32_read(fh, buffer, fsize);
|
||||
fat32_close(fh);
|
||||
|
||||
ttf_font_t *font = kmalloc(sizeof(ttf_font_t));
|
||||
if (!font) {
|
||||
kfree(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stbtt_fontinfo *info = kmalloc(sizeof(stbtt_fontinfo));
|
||||
if (!info) {
|
||||
kfree(buffer);
|
||||
kfree(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!stbtt_InitFont(info, buffer, 0)) {
|
||||
serial_write("[FONT] Failed to init font: ");
|
||||
serial_write(path);
|
||||
serial_write("\n");
|
||||
kfree(info);
|
||||
kfree(buffer);
|
||||
kfree(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font->data = buffer;
|
||||
font->size = fsize;
|
||||
font->info = info;
|
||||
font->pixel_height = size;
|
||||
font->scale = stbtt_ScaleForPixelHeight(info, size);
|
||||
|
||||
stbtt_GetFontVMetrics(info, &font->ascent, &font->descent, &font->line_gap);
|
||||
|
||||
if (!default_font) default_font = font;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void font_manager_render_char(ttf_font_t *font, int x, int y, char c, uint32_t color, void (*put_pixel_fn)(int, int, uint32_t)) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return;
|
||||
font_manager_render_char_scaled(font, x, y, c, color, font->pixel_height, put_pixel_fn);
|
||||
}
|
||||
|
||||
void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, void (*put_pixel_fn)(int, int, uint32_t)) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return;
|
||||
|
||||
stbtt_fontinfo *info = (stbtt_fontinfo *)font->info;
|
||||
|
||||
unsigned char *bitmap = NULL;
|
||||
int w, h, xoff, yoff;
|
||||
|
||||
float real_scale = stbtt_ScaleForPixelHeight(info, scale); // Convert pixel size back to stbtt scale
|
||||
|
||||
int codepoint = (unsigned char)c;
|
||||
if (codepoint == 128) codepoint = 0x2014; // — (—)
|
||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
||||
|
||||
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff);
|
||||
|
||||
if (bitmap) {
|
||||
for (int row = 0; row < h; row++) {
|
||||
for (int col = 0; col < w; col++) {
|
||||
unsigned char alpha = bitmap[row * w + col];
|
||||
if (alpha > 0) {
|
||||
int px = x + col + xoff;
|
||||
int py = y + row + yoff;
|
||||
uint32_t bg = graphics_get_pixel(px, py);
|
||||
put_pixel_fn(px, py, alpha_blend(bg, color, alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
stbtt_FreeBitmap(bitmap, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int font_manager_get_string_width(ttf_font_t *font, const char *s) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return 0;
|
||||
return font_manager_get_string_width_scaled(font, s, font->pixel_height);
|
||||
}
|
||||
|
||||
int font_manager_get_font_height_scaled(ttf_font_t *font, float scale) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return 0;
|
||||
float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale);
|
||||
return (int)((font->ascent - font->descent) * real_scale);
|
||||
}
|
||||
|
||||
int font_manager_get_font_ascent_scaled(ttf_font_t *font, float scale) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return 0;
|
||||
float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale);
|
||||
return (int)(font->ascent * real_scale);
|
||||
}
|
||||
|
||||
int font_manager_get_font_line_height_scaled(ttf_font_t *font, float scale) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return 0;
|
||||
float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale);
|
||||
return (int)((font->ascent - font->descent + font->line_gap) * real_scale);
|
||||
}
|
||||
|
||||
int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float scale) {
|
||||
if (!font) font = default_font;
|
||||
if (!font || !s) return 0;
|
||||
|
||||
stbtt_fontinfo *info = (stbtt_fontinfo *)font->info;
|
||||
float real_scale = stbtt_ScaleForPixelHeight(info, scale);
|
||||
int width = 0;
|
||||
while (*s) {
|
||||
int advance, lsb;
|
||||
int codepoint = (unsigned char)*s;
|
||||
if (codepoint == 128) codepoint = 0x2014; // — (—)
|
||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
||||
stbtt_GetCodepointHMetrics(info, codepoint, &advance, &lsb);
|
||||
// Round per-character to match draw_string's accumulation
|
||||
width += (int)(advance * real_scale + 0.5f);
|
||||
s++;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
108
src/kernel/gdt.c
@@ -1,108 +0,0 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "gdt.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "memory_manager.h"
|
||||
|
||||
static void *gdt_memset(void *s, int c, size_t n) {
|
||||
uint8_t *p = (uint8_t *)s;
|
||||
while (n--) {
|
||||
*p++ = (uint8_t)c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#define GDT_ENTRIES 7
|
||||
|
||||
struct gdt_entry gdt[GDT_ENTRIES];
|
||||
struct gdt_ptr gdtr;
|
||||
struct tss_entry tss;
|
||||
|
||||
extern void gdt_flush(uint64_t);
|
||||
extern void tss_flush(void);
|
||||
|
||||
static void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = ((limit >> 16) & 0x0F);
|
||||
|
||||
gdt[num].granularity |= (gran & 0xF0);
|
||||
gdt[num].access = access;
|
||||
}
|
||||
|
||||
static void gdt_set_tss_gate(int num, uint64_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||
// A TSS entry in x86_64 is 16 bytes (takes up 2 adjacent GDT entries)
|
||||
struct {
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_middle;
|
||||
uint8_t access;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
uint32_t base_upper;
|
||||
uint32_t reserved;
|
||||
} __attribute__((packed)) *tss_desc = (void*)&gdt[num];
|
||||
|
||||
tss_desc->base_low = (base & 0xFFFF);
|
||||
tss_desc->base_middle = (base >> 16) & 0xFF;
|
||||
tss_desc->base_high = (base >> 24) & 0xFF;
|
||||
tss_desc->base_upper = (base >> 32);
|
||||
|
||||
tss_desc->limit_low = (limit & 0xFFFF);
|
||||
tss_desc->granularity = ((limit >> 16) & 0x0F);
|
||||
|
||||
tss_desc->granularity |= (gran & 0xF0);
|
||||
tss_desc->access = access;
|
||||
tss_desc->reserved = 0;
|
||||
}
|
||||
|
||||
void tss_set_stack(uint64_t kernel_stack) {
|
||||
tss.rsp0 = kernel_stack;
|
||||
}
|
||||
|
||||
void gdt_init(void) {
|
||||
gdtr.limit = (sizeof(struct gdt_entry) * GDT_ENTRIES) - 1;
|
||||
gdtr.base = (uint64_t)&gdt;
|
||||
|
||||
// NULL segment
|
||||
gdt_set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
// Kernel Code segment (Ring 0, 64-bit)
|
||||
// 0x9A: Present(1), Ring(0), System(1), Executable(1), DirConforming(0), Readable(1), Accessed(0)
|
||||
// 0xAF: Long Mode (64-bit) (L=1, DB=0)
|
||||
gdt_set_gate(1, 0, 0, 0x9A, 0xAF);
|
||||
|
||||
// Kernel Data segment (Ring 0)
|
||||
// 0x92: Present(1), Ring(0), System(1), Executable(0), DirExpandDown(0), Writable(1), Accessed(0)
|
||||
gdt_set_gate(2, 0, 0, 0x92, 0xAF);
|
||||
|
||||
// User Data segment (Ring 3)
|
||||
// 0xF2: Present(1), Ring(3), System(1), Executable(0), DirExpandDown(0), Writable(1), Accessed(0)
|
||||
gdt_set_gate(3, 0, 0, 0xF2, 0xAF);
|
||||
|
||||
// User Code segment (Ring 3, 64-bit)
|
||||
// 0xFA: Present(1), Ring(3), System(1), Executable(1), DirConforming(0), Readable(1), Accessed(0)
|
||||
// 0xAF: Long Mode (64-bit)
|
||||
gdt_set_gate(4, 0, 0, 0xFA, 0xAF);
|
||||
|
||||
// TSS segment (takes entries 5 and 6 technically because it's 16 bytes)
|
||||
gdt_memset(&tss, 0, sizeof(struct tss_entry));
|
||||
tss.iopb_offset = sizeof(struct tss_entry);
|
||||
|
||||
// Allocate a default Ring 0 interrupt stack in case an interrupt fires early or
|
||||
// the scheduler hasn't set one up yet for a task.
|
||||
void* initial_tss_stack = kmalloc_aligned(4096, 4096);
|
||||
if (initial_tss_stack) {
|
||||
tss.rsp0 = (uint64_t)initial_tss_stack + 4096;
|
||||
}
|
||||
|
||||
gdt_set_tss_gate(5, (uint64_t)&tss, sizeof(struct tss_entry) - 1, 0x89, 0x00);
|
||||
|
||||
gdt_flush((uint64_t)&gdtr);
|
||||
tss_flush();
|
||||
}
|
||||
BIN
src/kernel/images/.DS_Store
vendored
BIN
src/kernel/images/wallpapers/.DS_Store
vendored
@@ -1,576 +0,0 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "fat32.h"
|
||||
#include <stddef.h>
|
||||
|
||||
// Helper function to calculate string length
|
||||
static size_t lic_strlen(const char *str) {
|
||||
size_t len = 0;
|
||||
while (str[len]) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
void write_license_file(void) {
|
||||
FAT32_FileHandle *fh = fat32_open("LICENSE", "w");
|
||||
if (fh) {
|
||||
const char *content =
|
||||
" GNU GENERAL PUBLIC LICENSE\n"
|
||||
" Version 3, 29 June 2007\n\n"
|
||||
" Copyright(C) Chris (boreddevnl) 2024-2026\n\n"
|
||||
" Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n"
|
||||
" Everyone is permitted to copy and distribute verbatim copies\n"
|
||||
" of this license document, but changing it is not allowed.\n\n"
|
||||
" Preamble\n\n"
|
||||
" The GNU General Public License is a free, copyleft license for\n"
|
||||
"software and other kinds of works.\n\n"
|
||||
" The licenses for most software and other practical works are designed\n"
|
||||
"to take away your freedom to share and change the works. By contrast,\n"
|
||||
"the GNU General Public License is intended to guarantee your freedom to\n"
|
||||
"share and change all versions of a program--to make sure it remains free\n"
|
||||
"software for all its users. We, the Free Software Foundation, use the\n"
|
||||
"GNU General Public License for most of our software; it applies also to\n"
|
||||
"any other work released this way by its authors. You can apply it to\n"
|
||||
"your programs, too.\n\n"
|
||||
" When we speak of free software, we are referring to freedom, not\n"
|
||||
"price. Our General Public Licenses are designed to make sure that you\n"
|
||||
"have the freedom to distribute copies of free software (and charge for\n"
|
||||
"them if you wish), that you receive source code or can get it if you\n"
|
||||
"want it, that you can change the software or use pieces of it in new\n"
|
||||
"free programs, and that you know you can do these things.\n\n"
|
||||
" To protect your rights, we need to prevent others from denying you\n"
|
||||
"these rights or asking you to surrender the rights. Therefore, you have\n"
|
||||
"certain responsibilities if you distribute copies of the software, or if\n"
|
||||
"you modify it: responsibilities to respect the freedom of others.\n\n"
|
||||
" For example, if you distribute copies of such a program, whether\n"
|
||||
"gratis or for a fee, you must pass on to the recipients the same\n"
|
||||
"freedoms that you received. You must make sure that they, too, receive\n"
|
||||
"or can get the source code. And you must show them these terms so they\n"
|
||||
"know their rights.\n\n"
|
||||
" Developers that use the GNU GPL protect your rights with two steps:\n"
|
||||
"(1) assert copyright on the software, and (2) offer you this License\n"
|
||||
"giving you legal permission to copy, distribute and/or modify it.\n\n"
|
||||
" For the developers' and authors' protection, the GPL clearly explains\n"
|
||||
"that there is no warranty for this free software. For both users' and\n"
|
||||
"authors' sake, the GPL requires that modified versions be marked as\n"
|
||||
"changed, so that their problems will not be attributed erroneously to\n"
|
||||
"authors of previous versions.\n\n"
|
||||
" Some devices are designed to deny users access to install or run\n"
|
||||
"modified versions of the software inside them, although the manufacturer\n"
|
||||
"can do so. This is fundamentally incompatible with the aim of\n"
|
||||
"protecting users' freedom to change the software. The systematic\n"
|
||||
"pattern of such abuse occurs in the area of products for individuals to\n"
|
||||
"use, which is precisely where it is most unacceptable. Therefore, we\n"
|
||||
"have designed this version of the GPL to prohibit the practice for those\n"
|
||||
"products. If such problems arise substantially in other domains, we\n"
|
||||
"stand ready to extend this provision to those domains in future versions\n"
|
||||
"of the GPL, as needed to protect the freedom of users.\n\n"
|
||||
" Finally, every program is threatened constantly by software patents.\n"
|
||||
"States should not allow patents to restrict development and use of\n"
|
||||
"software on general-purpose computers, but in those that do, we wish to\n"
|
||||
"avoid the special danger that patents applied to a free program could\n"
|
||||
"make it effectively proprietary. To prevent this, the GPL assures that\n"
|
||||
"patents cannot be used to render the program non-free.\n\n"
|
||||
" The precise terms and conditions for copying, distribution and\n"
|
||||
"modification follow.\n\n"
|
||||
" TERMS AND CONDITIONS\n\n"
|
||||
" 0. Definitions.\n\n"
|
||||
" \"This License\" refers to version 3 of the GNU General Public License.\n\n"
|
||||
" \"Copyright\" also means copyright-like laws that apply to other kinds of\n"
|
||||
"works, such as semiconductor masks.\n\n"
|
||||
" \"The Program\" refers to any copyrightable work licensed under this\n"
|
||||
"License. Each licensee is addressed as \"you\". \"Licensees\" and\n"
|
||||
"\"recipients\" may be individuals or organizations.\n\n"
|
||||
" To \"modify\" a work means to copy from or adapt all or part of the work\n"
|
||||
"in a fashion requiring copyright permission, other than the making of an\n"
|
||||
"exact copy. The resulting work is called a \"modified version\" of the\n"
|
||||
"earlier work or a work \"based on\" the earlier work.\n\n"
|
||||
" A \"covered work\" means either the unmodified Program or a work based\n"
|
||||
"on the Program.\n\n"
|
||||
" To \"propagate\" a work means to do anything with it that, without\n"
|
||||
"permission, would make you directly or secondarily liable for\n"
|
||||
"infringement under applicable copyright law, except executing it on a\n"
|
||||
"computer or modifying a private copy. Propagation includes copying,\n"
|
||||
"distribution (with or without modification), making available to the\n"
|
||||
"public, and in some countries other activities as well.\n\n"
|
||||
" To \"convey\" a work means any kind of propagation that enables other\n"
|
||||
"parties to make or receive copies. Mere interaction with a user through\n"
|
||||
"a computer network, with no transfer of a copy, is not conveying.\n\n"
|
||||
" An interactive user interface displays \"Appropriate Legal Notices\"\n"
|
||||
"to the extent that it includes a convenient and prominently visible\n"
|
||||
"feature that (1) displays an appropriate copyright notice, and (2)\n"
|
||||
"tells the user that there is no warranty for the work (except to the\n"
|
||||
"extent that warranties are provided), that licensees may convey the\n"
|
||||
"work under this License, and how to view a copy of this License. If\n"
|
||||
"the interface presents a list of user commands or options, such as a\n"
|
||||
"menu, a prominent item in the list meets this criterion.\n\n"
|
||||
" 1. Source Code.\n\n"
|
||||
" The \"source code\" for a work means the preferred form of the work\n"
|
||||
"for making modifications to it. \"Object code\" means any non-source\n"
|
||||
"form of a work.\n\n"
|
||||
" A \"Standard Interface\" means an interface that either is an official\n"
|
||||
"standard defined by a recognized standards body, or, in the case of\n"
|
||||
"interfaces specified for a particular programming language, one that\n"
|
||||
"is widely used among developers working in that language.\n\n"
|
||||
" The \"System Libraries\" of an executable work include anything, other\n"
|
||||
"than the work as a whole, that (a) is included in the normal form of\n"
|
||||
"packaging a Major Component, but which is not part of that Major\n"
|
||||
"Component, and (b) serves only to enable use of the work with that\n"
|
||||
"Major Component, or to implement a Standard Interface for which an\n"
|
||||
"implementation is available to the public in source code form. A\n"
|
||||
"\"Major Component\", in this context, means a major essential component\n"
|
||||
"(kernel, window system, and so on) of the specific operating system\n"
|
||||
"(if any) on which the executable work runs, or a compiler used to\n"
|
||||
"produce the work, or an object code interpreter used to run it.\n\n"
|
||||
" The \"Corresponding Source\" for a work in object code form means all\n"
|
||||
"the source code needed to generate, install, and (for an executable\n"
|
||||
"work) run the object code and to modify the work, including scripts to\n"
|
||||
"control those activities. However, it does not include the work's\n"
|
||||
"System Libraries, or general-purpose tools or generally available free\n"
|
||||
"programs which are used unmodified in performing those activities but\n"
|
||||
"which are not part of the work. For example, Corresponding Source\n"
|
||||
"includes interface definition files associated with source files for\n"
|
||||
"the work, and the source code for shared libraries and dynamically\n"
|
||||
"linked subprograms that the work is specifically designed to require,\n"
|
||||
"such as by intimate data communication or control flow between those\n"
|
||||
"subprograms and other parts of the work.\n\n"
|
||||
" The Corresponding Source need not include anything that users\n"
|
||||
"can regenerate automatically from other parts of the Corresponding\n"
|
||||
"Source.\n\n"
|
||||
" The Corresponding Source for a work in source code form is that\n"
|
||||
"same work.\n\n"
|
||||
" 2. Basic Permissions.\n\n"
|
||||
" All rights granted under this License are granted for the term of\n"
|
||||
"copyright on the Program, and are irrevocable provided the stated\n"
|
||||
"conditions are met. This License explicitly affirms your unlimited\n"
|
||||
"permission to run the unmodified Program. The output from running a\n"
|
||||
"covered work is covered by this License only if the output, given its\n"
|
||||
"content, constitutes a covered work. This License acknowledges your\n"
|
||||
"rights of fair use or other equivalent, as provided by copyright law.\n\n"
|
||||
" You may make, run and propagate covered works that you do not\n"
|
||||
"convey, without conditions so long as your license otherwise remains\n"
|
||||
"in force. You may convey covered works to others for the sole purpose\n"
|
||||
"of having them make modifications exclusively for you, or provide you\n"
|
||||
"with facilities for running those works, provided that you comply with\n"
|
||||
"the terms of this License in conveying all material for which you do\n"
|
||||
"not control copyright. Those thus making or running the covered works\n"
|
||||
"for you must do so exclusively on your behalf, under your direction\n"
|
||||
"and control, on terms that prohibit them from making any copies of\n"
|
||||
"your copyrighted material outside their relationship with you.\n\n"
|
||||
" Conveying under any other circumstances is permitted solely under\n"
|
||||
"the conditions stated below. Sublicensing is not allowed; section 10\n"
|
||||
"makes it unnecessary.\n\n"
|
||||
" 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n"
|
||||
" No covered work shall be deemed part of an effective technological\n"
|
||||
"measure under any applicable law fulfilling obligations under article\n"
|
||||
"11 of the WIPO copyright treaty adopted on 20 December 1996, or\n"
|
||||
"similar laws prohibiting or restricting circumvention of such\n"
|
||||
"measures.\n\n"
|
||||
" When you convey a covered work, you waive any legal power to forbid\n"
|
||||
"circumvention of technological measures to the extent such circumvention\n"
|
||||
"is effected by exercising rights under this License with respect to\n"
|
||||
"the covered work, and you disclaim any intention to limit operation or\n"
|
||||
"modification of the work as a means of enforcing, against the work's\n"
|
||||
"users, your or third parties' legal rights to forbid circumvention of\n"
|
||||
"technological measures.\n\n"
|
||||
" 4. Conveying Verbatim Copies.\n\n"
|
||||
" You may convey verbatim copies of the Program's source code as you\n"
|
||||
"receive it, in any medium, provided that you conspicuously and\n"
|
||||
"appropriately publish on each copy an appropriate copyright notice;\n"
|
||||
"keep intact all notices stating that this License and any\n"
|
||||
"non-permissive terms added in accord with section 7 apply to the code;\n"
|
||||
"keep intact all notices of the absence of any warranty; and give all\n"
|
||||
"recipients a copy of this License along with the Program.\n\n"
|
||||
" You may charge any price or no price for each copy that you convey,\n"
|
||||
"and you may offer support or warranty protection for a fee.\n\n"
|
||||
" 5. Conveying Modified Source Versions.\n\n"
|
||||
" You may convey a work based on the Program, or the modifications to\n"
|
||||
"produce it from the Program, in the form of source code under the\n"
|
||||
"terms of section 4, provided that you also meet all of these conditions:\n\n"
|
||||
" a) The work must carry prominent notices stating that you modified\n"
|
||||
" it, and giving a relevant date.\n\n"
|
||||
" b) The work must carry prominent notices stating that it is\n"
|
||||
" released under this License and any conditions added under section\n"
|
||||
" 7. This requirement modifies the requirement in section 4 to\n"
|
||||
" \"keep intact all notices\".\n\n"
|
||||
" c) You must license the entire work, as a whole, under this\n"
|
||||
" License to anyone who comes into possession of a copy. This\n"
|
||||
" License will therefore apply, along with any applicable section 7\n"
|
||||
" additional terms, to the whole of the work, and all its parts,\n"
|
||||
" regardless of how they are packaged. This License gives no\n"
|
||||
" permission to license the work in any other way, but it does not\n"
|
||||
" invalidate such permission if you have separately received it.\n\n"
|
||||
" d) If the work has interactive user interfaces, each must display\n"
|
||||
" Appropriate Legal Notices; however, if the Program has interactive\n"
|
||||
" interfaces that do not display Appropriate Legal Notices, your\n"
|
||||
" work need not make them do so.\n\n"
|
||||
" A compilation of a covered work with other separate and independent\n"
|
||||
"works, which are not by their nature extensions of the covered work,\n"
|
||||
"and which are not combined with it such as to form a larger program,\n"
|
||||
"in or on a volume of a storage or distribution medium, is called an\n"
|
||||
"\"aggregate\" if the compilation and its resulting copyright are not\n"
|
||||
"used to limit the access or legal rights of the compilation's users\n"
|
||||
"beyond what the individual works permit. Inclusion of a covered work\n"
|
||||
"in an aggregate does not cause this License to apply to the other\n"
|
||||
"parts of the aggregate.\n\n"
|
||||
" 6. Conveying Non-Source Forms.\n\n"
|
||||
" You may convey a covered work in object code form under the terms\n"
|
||||
"of sections 4 and 5, provided that you also convey the\n"
|
||||
"machine-readable Corresponding Source under the terms of this License,\n"
|
||||
"in one of these ways:\n\n"
|
||||
" a) Convey the object code in, or embodied in, a physical product\n"
|
||||
" (including a physical distribution medium), accompanied by the\n"
|
||||
" Corresponding Source fixed on a durable physical medium\n"
|
||||
" customarily used for software interchange.\n\n"
|
||||
" b) Convey the object code in, or embodied in, a physical product\n"
|
||||
" (including a physical distribution medium), accompanied by a\n"
|
||||
" written offer, valid for at least three years and valid for as\n"
|
||||
" long as you offer spare parts or customer support for that product\n"
|
||||
" model, to give anyone who possesses the object code either (1) a\n"
|
||||
" copy of the Corresponding Source for all the software in the\n"
|
||||
" product that is covered by this License, on a durable physical\n"
|
||||
" medium customarily used for software interchange, for a price no\n"
|
||||
" more than your reasonable cost of physically performing this\n"
|
||||
" conveying of source, or (2) access to copy the\n"
|
||||
" Corresponding Source from a network server at no charge.\n\n"
|
||||
" c) Convey individual copies of the object code with a copy of the\n"
|
||||
" written offer to provide the Corresponding Source. This\n"
|
||||
" alternative is allowed only occasionally and noncommercially, and\n"
|
||||
" only if you received the object code with such an offer, in accord\n"
|
||||
" with subsection 6b.\n\n"
|
||||
" d) Convey the object code by offering access from a designated\n"
|
||||
" place (gratis or for a charge), and offer equivalent access to the\n"
|
||||
" Corresponding Source in the same way through the same place at no\n"
|
||||
" further charge. You need not require recipients to copy the\n"
|
||||
" Corresponding Source along with the object code. If the place to\n"
|
||||
" copy the object code is a network server, the Corresponding Source\n"
|
||||
" may be on a different server (operated by you or a third party)\n"
|
||||
" that supports equivalent copying facilities, provided you maintain\n"
|
||||
" clear directions next to the object code saying where to find the\n"
|
||||
" Corresponding Source. Regardless of what server hosts the\n"
|
||||
" Corresponding Source, you remain obligated to ensure that it is\n"
|
||||
" available for as long as needed to satisfy these requirements.\n\n"
|
||||
" e) Convey the object code using peer-to-peer transmission, provided\n"
|
||||
" you inform other peers where the object code and Corresponding\n"
|
||||
" Source of the work are being offered to the general public at no\n"
|
||||
" charge under subsection 6d.\n\n"
|
||||
" A separable portion of the object code, whose source code is excluded\n"
|
||||
"from the Corresponding Source as a System Library, need not be\n"
|
||||
"included in conveying the object code work.\n\n"
|
||||
" A \"User Product\" is either (1) a \"consumer product\", which means any\n"
|
||||
"tangible personal property which is normally used for personal, family,\n"
|
||||
"or household purposes, or (2) anything designed or sold for incorporation\n"
|
||||
"into a dwelling. In determining whether a product is a consumer product,\n"
|
||||
"doubtful cases shall be resolved in favor of coverage. For a particular\n"
|
||||
"product received by a particular user, \"normally used\" refers to a\n"
|
||||
"typical or common use of that class of product, regardless of the status\n"
|
||||
"of the particular user or of the way in which the particular user\n"
|
||||
"actually uses, or expects or is expected to use, the product. A product\n"
|
||||
"is a consumer product regardless of whether the product has substantial\n"
|
||||
"commercial, industrial or non-consumer uses, unless such uses represent\n"
|
||||
"the only significant mode of use of the product.\n\n"
|
||||
" \"Installation Information\" for a User Product means any methods,\n"
|
||||
"procedures, authorization keys, or other information required to install\n"
|
||||
"and execute modified versions of a covered work in that User Product from\n"
|
||||
"a modified version of its Corresponding Source. The information must\n"
|
||||
"suffice to ensure that the continued functioning of the modified object\n"
|
||||
"code is in no case prevented or interfered with solely because\n"
|
||||
"modification has been made.\n\n"
|
||||
" If you convey an object code work under this section in, or with, or\n"
|
||||
"specifically for use in, a User Product, and the conveying occurs as\n"
|
||||
"part of a transaction in which the right of possession and use of the\n"
|
||||
"User Product is transferred to the recipient in perpetuity or for a\n"
|
||||
"fixed term (regardless of how the transaction is characterized), the\n"
|
||||
"Corresponding Source conveyed under this section must be accompanied\n"
|
||||
"by the Installation Information. But this requirement does not apply\n"
|
||||
"if neither you nor any third party retains the ability to install\n"
|
||||
"modified object code on the User Product (for example, the work has\n"
|
||||
"been installed in ROM).\n\n"
|
||||
" The requirement to provide Installation Information does not include a\n"
|
||||
"requirement to continue to provide support service, warranty, or updates\n"
|
||||
"for a work that has been modified or installed by the recipient, or for\n"
|
||||
"the User Product in which it has been modified or installed. Access to a\n"
|
||||
"network may be denied when the modification itself materially and\n"
|
||||
"adversely affects the operation of the network or violates the rules and\n"
|
||||
"protocols for communication across the network.\n\n"
|
||||
" Corresponding Source conveyed, and Installation Information provided,\n"
|
||||
"in accord with this section must be in a format that is publicly\n"
|
||||
"documented (and with an implementation available to the public in\n"
|
||||
"source code form), and must require no special password or key for\n"
|
||||
"unpacking, reading or copying.\n\n"
|
||||
" 7. Additional Terms.\n\n"
|
||||
" \"Additional permissions\" are terms that supplement the terms of this\n"
|
||||
"License by making exceptions from one or more of its conditions.\n"
|
||||
"Additional permissions that are applicable to the entire Program shall\n"
|
||||
"be treated as though they were included in this License, to the extent\n"
|
||||
"that they are valid under applicable law. If additional permissions\n"
|
||||
"apply only to part of the Program, that part may be used separately\n"
|
||||
"under those permissions, but the entire Program remains governed by\n"
|
||||
"this License without regard to the additional permissions.\n\n"
|
||||
" When you convey a copy of a covered work, you may at your option\n"
|
||||
"remove any additional permissions from that copy, or from any part of\n"
|
||||
"it. (Additional permissions may be written to require their own\n"
|
||||
"removal in certain cases when you modify the work.) You may place\n"
|
||||
"additional permissions on material, added by you to a covered work,\n"
|
||||
"for which you have or can give appropriate copyright permission.\n\n"
|
||||
" Notwithstanding any other provision of this License, for material you\n"
|
||||
"add to a covered work, you may (if authorized by the copyright holders of\n"
|
||||
"that material) supplement the terms of this License with terms:\n\n"
|
||||
" a) Disclaiming warranty or limiting liability differently from the\n"
|
||||
" terms of sections 15 and 16 of this License; or\n\n"
|
||||
" b) Requiring preservation of specified reasonable legal notices or\n"
|
||||
" author attributions in that material or in the Appropriate Legal\n"
|
||||
" Notices displayed by works containing it; or\n\n"
|
||||
" c) Prohibiting misrepresentation of the origin of that material, or\n"
|
||||
" requiring that modified versions of such material be marked in\n"
|
||||
" reasonable ways as different from the original version; or\n\n"
|
||||
" d) Limiting the use for publicity purposes of names of licensors or\n"
|
||||
" authors of the material; or\n\n"
|
||||
" e) Declining to grant rights under trademark law for use of some\n"
|
||||
" trade names, trademarks, or service marks; or\n\n"
|
||||
" f) Requiring indemnification of licensors and authors of that\n"
|
||||
" material by anyone who conveys the material (or modified versions of\n"
|
||||
" it) with contractual assumptions of liability to the recipient, for\n"
|
||||
" any liability that these contractual assumptions directly impose on\n"
|
||||
" those licensors and authors.\n\n"
|
||||
" All other non-permissive additional terms are considered \"further\n"
|
||||
"restrictions\" within the meaning of section 10. If the Program as you\n"
|
||||
"received it, or any part of it, contains a notice stating that it is\n"
|
||||
"governed by this License along with a term that is a further\n"
|
||||
"restriction, you may remove that term. If a license document contains\n"
|
||||
"a further restriction but permits relicensing or conveying under this\n"
|
||||
"License, you may add to a covered work material governed by the terms\n"
|
||||
"of that license document, provided that the further restriction does\n"
|
||||
"not survive such relicensing or conveying.\n\n"
|
||||
" If you add terms to a covered work in accord with this section, you\n"
|
||||
"must place, in the relevant source files, a statement of the\n"
|
||||
"additional terms that apply to those files, or a notice indicating\n"
|
||||
"where to find the applicable terms.\n\n"
|
||||
" Additional terms, permissive or non-permissive, may be stated in the\n"
|
||||
"form of a separately written license, or stated as exceptions;\n"
|
||||
"the above requirements apply either way.\n\n"
|
||||
" 8. Termination.\n\n"
|
||||
" You may not propagate or modify a covered work except as expressly\n"
|
||||
"provided under this License. Any attempt otherwise to propagate or\n"
|
||||
"modify it is void, and will automatically terminate your rights under\n"
|
||||
"this License (including any patent licenses granted under the third\n"
|
||||
"paragraph of section 11).\n\n"
|
||||
" However, if you cease all violation of this License, then your\n"
|
||||
"license from a particular copyright holder is reinstated (a)\n"
|
||||
"provisionally, unless and until the copyright holder explicitly and\n"
|
||||
"finally terminates your license, and (b) permanently, if the copyright\n"
|
||||
"holder fails to notify you of the violation by some reasonable means\n"
|
||||
"prior to 60 days after the cessation.\n\n"
|
||||
" Moreover, your license from a particular copyright holder is\n"
|
||||
"reinstated permanently if the copyright holder notifies you of the\n"
|
||||
"violation by some reasonable means, this is the first time you have\n"
|
||||
"received notice of violation of this License (for any work) from that\n"
|
||||
"copyright holder, and you cure the violation prior to 30 days after\n"
|
||||
"your receipt of the notice.\n\n"
|
||||
" Termination of your rights under this section does not terminate the\n"
|
||||
"licenses of parties who have received copies or rights from you under\n"
|
||||
"this License. If your rights have been terminated and not permanently\n"
|
||||
"reinstated, you do not qualify to receive new licenses for the same\n"
|
||||
"material under section 10.\n\n"
|
||||
" 9. Acceptance Not Required for Having Copies.\n\n"
|
||||
" You are not required to accept this License in order to receive or\n"
|
||||
"run a copy of the Program. Ancillary propagation of a covered work\n"
|
||||
"occurring solely as a consequence of using peer-to-peer transmission\n"
|
||||
"to receive a copy likewise does not require acceptance. However,\n"
|
||||
"nothing other than this License grants you permission to propagate or\n"
|
||||
"modify any covered work. These actions infringe copyright if you do\n"
|
||||
"not accept this License. Therefore, by modifying or propagating a\n"
|
||||
"covered work, you indicate your acceptance of this License to do so.\n\n"
|
||||
" 10. Automatic Licensing of Downstream Recipients.\n\n"
|
||||
" Each time you convey a covered work, the recipient automatically\n"
|
||||
"receives a license from the original licensors, to run, modify and\n"
|
||||
"propagate that work, subject to this License. You are not responsible\n"
|
||||
"for enforcing compliance by third parties with this License.\n\n"
|
||||
" An \"entity transaction\" is a transaction transferring control of an\n"
|
||||
"organization, or substantially all assets of one, or subdividing an\n"
|
||||
"organization, or merging organizations. If propagation of a covered\n"
|
||||
"work results from an entity transaction, each party to that\n"
|
||||
"transaction who receives a copy of the work also receives whatever\n"
|
||||
"licenses to the work the party's predecessor in interest had or could\n"
|
||||
"give under the previous paragraph, plus a right to possession of the\n"
|
||||
"Corresponding Source of the work from the predecessor in interest, if\n"
|
||||
"the predecessor has it or can get it with reasonable efforts.\n\n"
|
||||
" You may not impose any further restrictions on the exercise of the\n"
|
||||
"rights granted or affirmed under this License. For example, you may\n"
|
||||
"not impose a license fee, royalty, or other charge for exercise of\n"
|
||||
"rights granted under this License, and you may not initiate litigation\n"
|
||||
"(including a cross-claim or counterclaim in a lawsuit) alleging that\n"
|
||||
"any patent claim is infringed by making, using, selling, offering for\n"
|
||||
"sale, or importing the Program or any portion of it.\n\n"
|
||||
" 11. Patents.\n\n"
|
||||
" A \"contributor\" is a copyright holder who authorizes use under this\n"
|
||||
"License of the Program or a work on which the Program is based. The\n"
|
||||
"work thus licensed is called the contributor's \"contributor version\".\n\n"
|
||||
" A contributor's \"essential patent claims\" are all patent claims\n"
|
||||
"owned or controlled by the contributor, whether already acquired or\n"
|
||||
"hereafter acquired, that would be infringed by some manner, permitted\n"
|
||||
"by this License, of making, using, or selling its contributor version,\n"
|
||||
"but do not include claims that would be infringed only as a\n"
|
||||
"consequence of further modification of the contributor version. For\n"
|
||||
"purposes of this definition, \"control\" includes the right to grant\n"
|
||||
"patent sublicenses in a manner consistent with the requirements of\n"
|
||||
"this License.\n\n"
|
||||
" Each contributor grants you a non-exclusive, worldwide, royalty-free\n"
|
||||
"patent license under the contributor's essential patent claims, to\n"
|
||||
"make, use, sell, offer for sale, import and otherwise run, modify and\n"
|
||||
"propagate the contents of its contributor version.\n\n"
|
||||
" In the following three paragraphs, a \"patent license\" is any express\n"
|
||||
"agreement or commitment, however denominated, not to enforce a patent\n"
|
||||
"(such as an express permission to practice a patent or covenant not to\n"
|
||||
"sue for patent infringement). To \"grant\" such a patent license to a\n"
|
||||
"party means to make such an agreement or commitment not to enforce a\n"
|
||||
"patent against the party.\n\n"
|
||||
" If you convey a covered work, knowingly relying on a patent license,\n"
|
||||
"and the Corresponding Source of the work is not available for anyone\n"
|
||||
"to copy, free of charge and under the terms of this License, through a\n"
|
||||
"publicly available network server or other readily accessible means,\n"
|
||||
"then you must either (1) cause the Corresponding Source to be so\n"
|
||||
"available, or (2) arrange to deprive yourself of the benefit of the\n"
|
||||
"patent license for this particular work, or (3) arrange, in a manner\n"
|
||||
"consistent with the requirements of this License, to extend the patent\n"
|
||||
"license to downstream recipients. \"Knowingly relying\" means you have\n"
|
||||
"actual knowledge that, but for the patent license, your conveying the\n"
|
||||
"covered work in a country, or your recipient's use of the covered work\n"
|
||||
"in a country, would infringe one or more identifiable patents in that\n"
|
||||
"country that you have reason to believe are valid.\n\n"
|
||||
" If, pursuant to or in connection with a single transaction or\n"
|
||||
"arrangement, you convey, or propagate by procuring conveyance of, a\n"
|
||||
"covered work, and grant a patent license to some of the parties\n"
|
||||
"receiving the covered work authorizing them to use, propagate, modify\n"
|
||||
"or convey a specific copy of the covered work, then the patent license\n"
|
||||
"you grant is automatically extended to all recipients of the covered\n"
|
||||
"work and works based on it.\n\n"
|
||||
" A patent license is \"discriminatory\" if it does not include within\n"
|
||||
"the scope of its coverage, prohibits the exercise of, or is\n"
|
||||
"conditioned on the non-exercise of one or more of the rights that are\n"
|
||||
"specifically granted under this License. You may not convey a covered\n"
|
||||
"work if you are a party to an arrangement with a third party that is\n"
|
||||
"in the business of distributing software, under which you make payment\n"
|
||||
"to the third party based on the extent of your activity of conveying\n"
|
||||
"the work, and under which the third party grants, to any of the\n"
|
||||
"parties who would receive the covered work from you, a discriminatory\n"
|
||||
"patent license (a) in connection with copies of the covered work\n"
|
||||
"conveyed by you (or copies made from those copies), or (b) primarily\n"
|
||||
"for and in connection with specific products or compilations that\n"
|
||||
"contain the covered work, unless you entered into that arrangement,\n"
|
||||
"or that patent license was granted, prior to 28 March 2007.\n\n"
|
||||
" Nothing in this License shall be construed as excluding or limiting\n"
|
||||
"any implied license or other defenses to infringement that may\n"
|
||||
"otherwise be available to you under applicable patent law.\n\n"
|
||||
" 12. No Surrender of Others' Freedom.\n\n"
|
||||
" If conditions are imposed on you (whether by court order, agreement or\n"
|
||||
"otherwise) that contradict the conditions of this License, they do not\n"
|
||||
"excuse you from the conditions of this License. If you cannot convey a\n"
|
||||
"covered work so as to satisfy simultaneously your obligations under this\n"
|
||||
"License and any other pertinent obligations, then as a consequence you may\n"
|
||||
"not convey it at all. For example, if you agree to terms that obligate you\n"
|
||||
"to collect a royalty for further conveying from those to whom you convey\n"
|
||||
"the Program, the only way you could satisfy both those terms and this\n"
|
||||
"License would be to refrain entirely from conveying the Program.\n\n"
|
||||
" 13. Use with the GNU Affero General Public License.\n\n"
|
||||
" Notwithstanding any other provision of this License, you have\n"
|
||||
"permission to link or combine any covered work with a work licensed\n"
|
||||
"under version 3 of the GNU Affero General Public License into a single\n"
|
||||
"combined work, and to convey the resulting work. The terms of this\n"
|
||||
"License will continue to apply to the part which is the covered work,\n"
|
||||
"but the special requirements of the GNU Affero General Public License,\n"
|
||||
"section 13, concerning interaction through a network will apply to the\n"
|
||||
"combination as such.\n\n"
|
||||
" 14. Revised Versions of this License.\n\n"
|
||||
" The Free Software Foundation may publish revised and/or new versions of\n"
|
||||
"the GNU General Public License from time to time. Such new versions will\n"
|
||||
"be similar in spirit to the present version, but may differ in detail to\n"
|
||||
"address new problems or concerns.\n\n"
|
||||
" Each version is given a distinguishing version number. If the\n"
|
||||
"Program specifies that a certain numbered version of the GNU General\n"
|
||||
"Public License \"or any later version\" applies to it, you have the\n"
|
||||
"option of following the terms and conditions either of that numbered\n"
|
||||
"version or of any later version published by the Free Software\n"
|
||||
"Foundation. If the Program does not specify a version number of the\n"
|
||||
"GNU General Public License, you may choose any version ever published\n"
|
||||
"by the Free Software Foundation.\n\n"
|
||||
" If the Program specifies that a proxy can decide which future\n"
|
||||
"versions of the GNU General Public License can be used, that proxy's\n"
|
||||
"public statement of acceptance of a version permanently authorizes you\n"
|
||||
"to choose that version for the Program.\n\n"
|
||||
" Later license versions may give you additional or different\n"
|
||||
"permissions. However, no additional obligations are imposed on any\n"
|
||||
"author or copyright holder as a result of your choosing to follow a\n"
|
||||
"later version.\n\n"
|
||||
" 15. Disclaimer of Warranty.\n\n"
|
||||
" THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n"
|
||||
"APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\n"
|
||||
"HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\n"
|
||||
"OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\n"
|
||||
"THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n"
|
||||
"PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\n"
|
||||
"IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\n"
|
||||
"ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n"
|
||||
" 16. Limitation of Liability.\n\n"
|
||||
" IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
|
||||
"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\n"
|
||||
"THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\n"
|
||||
"GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\n"
|
||||
"USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n"
|
||||
"DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n"
|
||||
"PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\n"
|
||||
"EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\n"
|
||||
"SUCH DAMAGES.\n\n"
|
||||
" 17. Interpretation of Sections 15 and 16.\n\n"
|
||||
" If the disclaimer of warranty and limitation of liability provided\n"
|
||||
"above cannot be given local legal effect according to their terms,\n"
|
||||
"reviewing courts shall apply local law that most closely approximates\n"
|
||||
"an absolute waiver of all civil liability in connection with the\n"
|
||||
"Program, unless a warranty or assumption of liability accompanies a\n"
|
||||
"copy of the Program in return for a fee.\n\n"
|
||||
" END OF TERMS AND CONDITIONS\n\n"
|
||||
" How to Apply These Terms to Your New Programs\n\n"
|
||||
" If you develop a new program, and you want it to be of the greatest\n"
|
||||
"possible use to the public, the best way to achieve this is to make it\n"
|
||||
"free software which everyone can redistribute and change under these terms.\n\n"
|
||||
" To do so, attach the following notices to the program. It is safest\n"
|
||||
"to attach them to the start of each source file to most effectively\n"
|
||||
"state the exclusion of warranty; and each file should have at least\n"
|
||||
"the \"copyright\" line and a pointer to where the full notice is found.\n\n"
|
||||
" <one line to give the program's name and a brief idea of what it does.>\n"
|
||||
" Copyright (C) <year> <name of author>\n\n"
|
||||
" This program is free software: you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation, either version 3 of the License, or\n"
|
||||
" (at your option) any later version.\n\n"
|
||||
" This program is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with this program. If not, see <https://www.gnu.org/licenses/>.\n\n"
|
||||
"Also add information on how to contact you by electronic and paper mail.\n\n"
|
||||
" If the program does terminal interaction, make it output a short\n"
|
||||
"notice like this when it starts in an interactive mode:\n\n"
|
||||
" <program> Copyright (C) <year> <name of author>\n"
|
||||
" This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n"
|
||||
" This is free software, and you are welcome to redistribute it\n"
|
||||
" under certain conditions; type `show c' for details.\n\n"
|
||||
"The hypothetical commands `show w' and `show c' should show the appropriate\n"
|
||||
"parts of the General Public License. Of course, your program's commands\n"
|
||||
"might be different; for a GUI interface, you would use an \"about box\".\n\n"
|
||||
" You should also get your employer (if you work as a programmer) or school,\n"
|
||||
"if any, to sign a \"copyright disclaimer\" for the program, if necessary.\n"
|
||||
"For more information on this, and how to apply and follow the GNU GPL, see\n"
|
||||
"<https://www.gnu.org/licenses/>.\n\n"
|
||||
" The GNU General Public License does not permit incorporating your program\n"
|
||||
"into proprietary programs. If your program is a subroutine library, you\n"
|
||||
"may consider it more useful to permit linking proprietary applications with\n"
|
||||
"the library. If this is what you want to do, use the GNU Lesser General\n"
|
||||
"Public License instead of this License. But first, please read\n"
|
||||
"<https://www.gnu.org/licenses/why-not-lgpl.html>.\n";
|
||||
|
||||
fat32_write(fh, (void *)content, lic_strlen(content));
|
||||
fat32_close(fh);
|
||||
}
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "syscall.h"
|
||||
#include "libui.h"
|
||||
#include <stdbool.h>
|
||||
#include "stdlib.h"
|
||||
|
||||
#define SCALE 1000000LL
|
||||
|
||||
#define COLOR_DARK_BG 0xFF1E1E1E
|
||||
#define COLOR_DARK_PANEL 0xFF2D2D2D
|
||||
#define COLOR_DARK_TEXT 0xFFF0F0F0
|
||||
#define COLOR_DARK_BORDER 0xFF3A3A3A
|
||||
|
||||
static ui_window_t win_calculator;
|
||||
|
||||
static long long calc_acc = 0;
|
||||
static long long calc_curr = 0;
|
||||
static char calc_op = 0;
|
||||
static bool calc_new_entry = true;
|
||||
static bool calc_error = false;
|
||||
static bool calc_decimal_mode = false;
|
||||
static long long calc_decimal_divisor = 10;
|
||||
static char display_buffer[1024];
|
||||
static int display_buf_len = 0;
|
||||
|
||||
static long long isqrt(long long n) {
|
||||
if (n < 0) return -1;
|
||||
if (n == 0) return 0;
|
||||
long long x = n;
|
||||
long long y = 1;
|
||||
while (x > y) {
|
||||
x = (x + y) / 2;
|
||||
y = n / x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static void fixed_to_str(long long n, char *buf) {
|
||||
if (n == 0) {
|
||||
buf[0] = '0'; buf[1] = 0; return;
|
||||
}
|
||||
char temp[64];
|
||||
int pos = 0;
|
||||
bool neg = n < 0;
|
||||
if (neg) n = -n;
|
||||
long long int_part = n / SCALE;
|
||||
long long frac_part = n % SCALE;
|
||||
|
||||
char frac_buf[16];
|
||||
int f_idx = 0;
|
||||
for(int k=0; k<6; k++) {
|
||||
long long div = 100000;
|
||||
for(int m=0; m<k; m++) div /= 10;
|
||||
frac_buf[f_idx++] = '0' + ((frac_part / div) % 10);
|
||||
}
|
||||
frac_buf[f_idx] = 0;
|
||||
while (f_idx > 0 && frac_buf[f_idx-1] == '0') f_idx--;
|
||||
frac_buf[f_idx] = 0;
|
||||
if (f_idx > 0) {
|
||||
for (int i = f_idx - 1; i >= 0; i--) temp[pos++] = frac_buf[i];
|
||||
temp[pos++] = '.';
|
||||
}
|
||||
if (int_part == 0) {
|
||||
temp[pos++] = '0';
|
||||
} else {
|
||||
while (int_part > 0) {
|
||||
temp[pos++] = '0' + (int_part % 10);
|
||||
int_part /= 10;
|
||||
}
|
||||
}
|
||||
if (neg) temp[pos++] = '-';
|
||||
int j = 0;
|
||||
while (pos > 0) buf[j++] = temp[--pos];
|
||||
buf[j] = 0;
|
||||
}
|
||||
|
||||
static void update_display(void) {
|
||||
if (calc_error) {
|
||||
char *err = "Error";
|
||||
int i = 0; while(err[i]) { display_buffer[i] = err[i]; i++; }
|
||||
display_buffer[i] = 0;
|
||||
} else {
|
||||
fixed_to_str(calc_curr, display_buffer);
|
||||
}
|
||||
display_buf_len = 0; while(display_buffer[display_buf_len]) display_buf_len++;
|
||||
}
|
||||
|
||||
static void calculator_paint(void) {
|
||||
int w = 180;
|
||||
int h = 230;
|
||||
ui_draw_rect(win_calculator, 4, 4, w - 8, h - 34, COLOR_DARK_BG);
|
||||
ui_draw_rounded_rect_filled(win_calculator, 10, 10, w - 20, 25, 6, COLOR_DARK_PANEL);
|
||||
|
||||
int text_w = display_buf_len * 8;
|
||||
int text_x = w - 15 - text_w;
|
||||
ui_draw_string(win_calculator, text_x, 18, display_buffer, COLOR_DARK_TEXT);
|
||||
|
||||
const char *labels[] = {
|
||||
"C", "sqr", "rt", "/",
|
||||
"7", "8", "9", "*",
|
||||
"4", "5", "6", "-",
|
||||
"1", "2", "3", "+",
|
||||
"0", ".", "BS", "="
|
||||
};
|
||||
|
||||
int bw = 35;
|
||||
int bh = 25;
|
||||
int gap = 5;
|
||||
int start_x = 10;
|
||||
int start_y = 40;
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int r = i / 4;
|
||||
int c = i % 4;
|
||||
ui_draw_rounded_rect_filled(win_calculator, start_x + c*(bw+gap), start_y + r*(bh+gap), bw, bh, 4, COLOR_DARK_BORDER);
|
||||
int label_x = start_x + c*(bw+gap) + 5;
|
||||
int label_y = start_y + r*(bh+gap) + 9;
|
||||
ui_draw_string(win_calculator, label_x, label_y, labels[i], COLOR_DARK_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_op(void) {
|
||||
if (calc_op == '+') calc_acc += calc_curr;
|
||||
else if (calc_op == '-') calc_acc -= calc_curr;
|
||||
else if (calc_op == '*') {
|
||||
calc_acc = (calc_acc * calc_curr) / SCALE;
|
||||
}
|
||||
else if (calc_op == '/') {
|
||||
if (calc_curr == 0) calc_error = true;
|
||||
else calc_acc = (calc_acc * SCALE) / calc_curr;
|
||||
} else {
|
||||
calc_acc = calc_curr;
|
||||
}
|
||||
}
|
||||
|
||||
static void calculator_click(int x, int y) {
|
||||
int bw = 35;
|
||||
int bh = 25;
|
||||
int gap = 5;
|
||||
int start_x = 10;
|
||||
int start_y = 35; // Matches the hitboxes
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int r = i / 4;
|
||||
int c = i % 4;
|
||||
int bx = start_x + c*(bw+gap);
|
||||
int by = start_y + r*(bh+gap);
|
||||
|
||||
if (x >= bx && x < bx + bw && y >= by && y < by + bh) {
|
||||
const char *labels[] = {
|
||||
"C", "s", "r", "/",
|
||||
"7", "8", "9", "*",
|
||||
"4", "5", "6", "-",
|
||||
"1", "2", "3", "+",
|
||||
"0", ".", "B", "="
|
||||
};
|
||||
char lbl = labels[i][0];
|
||||
|
||||
if (lbl >= '0' && lbl <= '9') {
|
||||
if (calc_new_entry || calc_error) {
|
||||
calc_curr = (lbl - '0') * SCALE;
|
||||
calc_new_entry = false;
|
||||
calc_decimal_mode = false;
|
||||
} else {
|
||||
if (calc_decimal_mode) {
|
||||
if (calc_decimal_divisor <= SCALE) {
|
||||
long long digit_val = ((long long)(lbl - '0') * SCALE) / calc_decimal_divisor;
|
||||
if (calc_curr >= 0) calc_curr += digit_val;
|
||||
else calc_curr -= digit_val;
|
||||
calc_decimal_divisor *= 10;
|
||||
}
|
||||
} else {
|
||||
if (calc_curr >= 0) calc_curr = calc_curr * 10 + (lbl - '0') * SCALE;
|
||||
else calc_curr = calc_curr * 10 - (lbl - '0') * SCALE;
|
||||
}
|
||||
}
|
||||
calc_error = false;
|
||||
} else if (lbl == '.') {
|
||||
if (calc_new_entry) {
|
||||
calc_curr = 0;
|
||||
calc_new_entry = false;
|
||||
}
|
||||
if (!calc_decimal_mode) {
|
||||
calc_decimal_mode = true;
|
||||
calc_decimal_divisor = 10;
|
||||
}
|
||||
} else if (lbl == 'C') {
|
||||
calc_curr = 0; calc_acc = 0; calc_op = 0;
|
||||
calc_new_entry = true; calc_error = false; calc_decimal_mode = false;
|
||||
} else if (lbl == 'B') {
|
||||
if (!calc_new_entry && !calc_error) {
|
||||
if (calc_decimal_mode) {
|
||||
if (calc_decimal_divisor > 10) {
|
||||
calc_decimal_divisor /= 10;
|
||||
long long unit = SCALE / calc_decimal_divisor;
|
||||
calc_curr = (calc_curr / (unit * 10)) * (unit * 10);
|
||||
} else {
|
||||
calc_decimal_mode = false;
|
||||
calc_decimal_divisor = 10;
|
||||
calc_curr = (calc_curr / SCALE) * SCALE;
|
||||
}
|
||||
} else {
|
||||
calc_curr = (calc_curr / SCALE / 10) * SCALE;
|
||||
}
|
||||
}
|
||||
} else if (lbl == 's') { // sqr
|
||||
calc_curr = (calc_curr * calc_curr) / SCALE; calc_new_entry = true;
|
||||
} else if (lbl == 'r') { // rt
|
||||
long long s = isqrt(calc_curr);
|
||||
if (s == -1) calc_error = true;
|
||||
else calc_curr = s * 1000;
|
||||
calc_new_entry = true;
|
||||
} else if (lbl == '=') {
|
||||
do_op();
|
||||
calc_curr = calc_acc; calc_op = 0; calc_new_entry = true; calc_decimal_mode = false;
|
||||
} else {
|
||||
if (!calc_new_entry) {
|
||||
if (calc_op) do_op();
|
||||
else calc_acc = calc_curr;
|
||||
}
|
||||
calc_op = lbl; calc_new_entry = true; calc_decimal_mode = false;
|
||||
}
|
||||
|
||||
update_display();
|
||||
calculator_paint();
|
||||
ui_mark_dirty(win_calculator, 0, 0, 180, 230);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
win_calculator = ui_window_create("Calculator", 200, 200, 180, 230);
|
||||
|
||||
calc_curr = 0;
|
||||
calc_acc = 0;
|
||||
calc_op = 0;
|
||||
calc_new_entry = true;
|
||||
update_display();
|
||||
|
||||
calculator_paint();
|
||||
ui_mark_dirty(win_calculator, 0, 0, 180, 230);
|
||||
|
||||
gui_event_t ev;
|
||||
while (1) {
|
||||
if (ui_get_event(win_calculator, &ev)) {
|
||||
if (ev.type == GUI_EVENT_PAINT) {
|
||||
calculator_paint();
|
||||
ui_mark_dirty(win_calculator, 0, 0, 180, 230);
|
||||
} else if (ev.type == GUI_EVENT_CLICK) {
|
||||
calculator_click(ev.arg1, ev.arg2);
|
||||
} else if (ev.type == GUI_EVENT_CLOSE) {
|
||||
sys_exit(0);
|
||||
}
|
||||
} else {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{95A126D2-CC94-4840-BF05-80305041B5FB}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>doomgeneric</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DisableSpecificWarnings>4146;4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DisableSpecificWarnings>4146;4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DisableSpecificWarnings>4146;4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DisableSpecificWarnings>4146;4996</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="am_map.c" />
|
||||
<ClCompile Include="doomdef.c" />
|
||||
<ClCompile Include="doomgeneric.c" />
|
||||
<ClCompile Include="doomgeneric_win.c" />
|
||||
<ClCompile Include="doomstat.c" />
|
||||
<ClCompile Include="dstrings.c" />
|
||||
<ClCompile Include="dummy.c" />
|
||||
<ClCompile Include="d_event.c" />
|
||||
<ClCompile Include="d_items.c" />
|
||||
<ClCompile Include="d_iwad.c" />
|
||||
<ClCompile Include="d_loop.c" />
|
||||
<ClCompile Include="d_main.c" />
|
||||
<ClCompile Include="d_mode.c" />
|
||||
<ClCompile Include="d_net.c" />
|
||||
<ClCompile Include="f_finale.c" />
|
||||
<ClCompile Include="f_wipe.c" />
|
||||
<ClCompile Include="gusconf.c" />
|
||||
<ClCompile Include="g_game.c" />
|
||||
<ClCompile Include="hu_lib.c" />
|
||||
<ClCompile Include="hu_stuff.c" />
|
||||
<ClCompile Include="icon.c" />
|
||||
<ClCompile Include="info.c" />
|
||||
<ClCompile Include="i_cdmus.c" />
|
||||
<ClCompile Include="i_endoom.c" />
|
||||
<ClCompile Include="i_input.c" />
|
||||
<ClCompile Include="i_joystick.c" />
|
||||
<ClCompile Include="i_scale.c" />
|
||||
<ClCompile Include="i_sound.c" />
|
||||
<ClCompile Include="i_system.c" />
|
||||
<ClCompile Include="i_timer.c" />
|
||||
<ClCompile Include="i_video.c" />
|
||||
<ClCompile Include="memio.c" />
|
||||
<ClCompile Include="m_argv.c" />
|
||||
<ClCompile Include="m_bbox.c" />
|
||||
<ClCompile Include="m_cheat.c" />
|
||||
<ClCompile Include="m_config.c" />
|
||||
<ClCompile Include="m_controls.c" />
|
||||
<ClCompile Include="m_fixed.c" />
|
||||
<ClCompile Include="m_menu.c" />
|
||||
<ClCompile Include="m_misc.c" />
|
||||
<ClCompile Include="m_random.c" />
|
||||
<ClCompile Include="p_ceilng.c" />
|
||||
<ClCompile Include="p_doors.c" />
|
||||
<ClCompile Include="p_enemy.c" />
|
||||
<ClCompile Include="p_floor.c" />
|
||||
<ClCompile Include="p_inter.c" />
|
||||
<ClCompile Include="p_lights.c" />
|
||||
<ClCompile Include="p_map.c" />
|
||||
<ClCompile Include="p_maputl.c" />
|
||||
<ClCompile Include="p_mobj.c" />
|
||||
<ClCompile Include="p_plats.c" />
|
||||
<ClCompile Include="p_pspr.c" />
|
||||
<ClCompile Include="p_saveg.c" />
|
||||
<ClCompile Include="p_setup.c" />
|
||||
<ClCompile Include="p_sight.c" />
|
||||
<ClCompile Include="p_spec.c" />
|
||||
<ClCompile Include="p_switch.c" />
|
||||
<ClCompile Include="p_telept.c" />
|
||||
<ClCompile Include="p_tick.c" />
|
||||
<ClCompile Include="p_user.c" />
|
||||
<ClCompile Include="r_bsp.c" />
|
||||
<ClCompile Include="r_data.c" />
|
||||
<ClCompile Include="r_draw.c" />
|
||||
<ClCompile Include="r_main.c" />
|
||||
<ClCompile Include="r_plane.c" />
|
||||
<ClCompile Include="r_segs.c" />
|
||||
<ClCompile Include="r_sky.c" />
|
||||
<ClCompile Include="r_things.c" />
|
||||
<ClCompile Include="sha1.c" />
|
||||
<ClCompile Include="sounds.c" />
|
||||
<ClCompile Include="statdump.c" />
|
||||
<ClCompile Include="st_lib.c" />
|
||||
<ClCompile Include="st_stuff.c" />
|
||||
<ClCompile Include="s_sound.c" />
|
||||
<ClCompile Include="tables.c" />
|
||||
<ClCompile Include="v_video.c" />
|
||||
<ClCompile Include="wi_stuff.c" />
|
||||
<ClCompile Include="w_checksum.c" />
|
||||
<ClCompile Include="w_file.c" />
|
||||
<ClCompile Include="w_file_stdc.c" />
|
||||
<ClCompile Include="w_main.c" />
|
||||
<ClCompile Include="w_wad.c" />
|
||||
<ClCompile Include="z_zone.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="am_map.h" />
|
||||
<ClInclude Include="config.h" />
|
||||
<ClInclude Include="deh_main.h" />
|
||||
<ClInclude Include="deh_misc.h" />
|
||||
<ClInclude Include="deh_str.h" />
|
||||
<ClInclude Include="doom.h" />
|
||||
<ClInclude Include="doomdata.h" />
|
||||
<ClInclude Include="doomdef.h" />
|
||||
<ClInclude Include="doomfeatures.h" />
|
||||
<ClInclude Include="doomgeneric.h" />
|
||||
<ClInclude Include="doomkeys.h" />
|
||||
<ClInclude Include="doomstat.h" />
|
||||
<ClInclude Include="doomtype.h" />
|
||||
<ClInclude Include="dstrings.h" />
|
||||
<ClInclude Include="d_englsh.h" />
|
||||
<ClInclude Include="d_event.h" />
|
||||
<ClInclude Include="d_items.h" />
|
||||
<ClInclude Include="d_iwad.h" />
|
||||
<ClInclude Include="d_loop.h" />
|
||||
<ClInclude Include="d_main.h" />
|
||||
<ClInclude Include="d_mode.h" />
|
||||
<ClInclude Include="d_player.h" />
|
||||
<ClInclude Include="d_textur.h" />
|
||||
<ClInclude Include="d_think.h" />
|
||||
<ClInclude Include="d_ticcmd.h" />
|
||||
<ClInclude Include="f_finale.h" />
|
||||
<ClInclude Include="f_wipe.h" />
|
||||
<ClInclude Include="gusconf.h" />
|
||||
<ClInclude Include="g_game.h" />
|
||||
<ClInclude Include="hu_lib.h" />
|
||||
<ClInclude Include="hu_stuff.h" />
|
||||
<ClInclude Include="info.h" />
|
||||
<ClInclude Include="i_cdmus.h" />
|
||||
<ClInclude Include="i_endoom.h" />
|
||||
<ClInclude Include="i_joystick.h" />
|
||||
<ClInclude Include="i_scale.h" />
|
||||
<ClInclude Include="i_sound.h" />
|
||||
<ClInclude Include="i_swap.h" />
|
||||
<ClInclude Include="i_system.h" />
|
||||
<ClInclude Include="i_timer.h" />
|
||||
<ClInclude Include="i_video.h" />
|
||||
<ClInclude Include="memio.h" />
|
||||
<ClInclude Include="m_argv.h" />
|
||||
<ClInclude Include="m_bbox.h" />
|
||||
<ClInclude Include="m_cheat.h" />
|
||||
<ClInclude Include="m_config.h" />
|
||||
<ClInclude Include="m_controls.h" />
|
||||
<ClInclude Include="m_fixed.h" />
|
||||
<ClInclude Include="m_menu.h" />
|
||||
<ClInclude Include="m_misc.h" />
|
||||
<ClInclude Include="m_random.h" />
|
||||
<ClInclude Include="net_client.h" />
|
||||
<ClInclude Include="net_dedicated.h" />
|
||||
<ClInclude Include="net_defs.h" />
|
||||
<ClInclude Include="net_gui.h" />
|
||||
<ClInclude Include="net_io.h" />
|
||||
<ClInclude Include="net_loop.h" />
|
||||
<ClInclude Include="net_packet.h" />
|
||||
<ClInclude Include="net_query.h" />
|
||||
<ClInclude Include="net_sdl.h" />
|
||||
<ClInclude Include="net_server.h" />
|
||||
<ClInclude Include="p_inter.h" />
|
||||
<ClInclude Include="p_local.h" />
|
||||
<ClInclude Include="p_mobj.h" />
|
||||
<ClInclude Include="p_pspr.h" />
|
||||
<ClInclude Include="p_saveg.h" />
|
||||
<ClInclude Include="p_setup.h" />
|
||||
<ClInclude Include="p_spec.h" />
|
||||
<ClInclude Include="p_tick.h" />
|
||||
<ClInclude Include="r_bsp.h" />
|
||||
<ClInclude Include="r_data.h" />
|
||||
<ClInclude Include="r_defs.h" />
|
||||
<ClInclude Include="r_draw.h" />
|
||||
<ClInclude Include="r_local.h" />
|
||||
<ClInclude Include="r_main.h" />
|
||||
<ClInclude Include="r_plane.h" />
|
||||
<ClInclude Include="r_segs.h" />
|
||||
<ClInclude Include="r_sky.h" />
|
||||
<ClInclude Include="r_state.h" />
|
||||
<ClInclude Include="r_things.h" />
|
||||
<ClInclude Include="sha1.h" />
|
||||
<ClInclude Include="sounds.h" />
|
||||
<ClInclude Include="statdump.h" />
|
||||
<ClInclude Include="st_lib.h" />
|
||||
<ClInclude Include="st_stuff.h" />
|
||||
<ClInclude Include="s_sound.h" />
|
||||
<ClInclude Include="tables.h" />
|
||||
<ClInclude Include="v_patch.h" />
|
||||
<ClInclude Include="v_video.h" />
|
||||
<ClInclude Include="wi_stuff.h" />
|
||||
<ClInclude Include="w_checksum.h" />
|
||||
<ClInclude Include="w_file.h" />
|
||||
<ClInclude Include="w_main.h" />
|
||||
<ClInclude Include="w_merge.h" />
|
||||
<ClInclude Include="w_wad.h" />
|
||||
<ClInclude Include="z_zone.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,558 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="am_map.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_event.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_items.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_iwad.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_loop.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_mode.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d_net.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="doomdef.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="doomstat.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dstrings.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dummy.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="f_finale.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="f_wipe.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="g_game.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gusconf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hu_lib.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hu_stuff.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_cdmus.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_endoom.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_joystick.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_scale.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_sound.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_system.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_timer.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="icon.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="info.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_argv.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_bbox.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_cheat.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_controls.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_fixed.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_menu.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_misc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="m_random.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="memio.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_ceilng.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_doors.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_enemy.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_floor.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_inter.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_lights.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_map.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_maputl.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_mobj.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_plats.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_pspr.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_saveg.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_setup.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_sight.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_spec.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_switch.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_telept.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_tick.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="p_user.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_bsp.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_data.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_draw.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_plane.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_segs.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_sky.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="r_things.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="s_sound.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sha1.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sounds.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="st_lib.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="st_stuff.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="statdump.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tables.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="v_video.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="w_checksum.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="w_file.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="w_file_stdc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="w_main.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="w_wad.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wi_stuff.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="z_zone.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="doomgeneric.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="doomgeneric_win.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_input.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="i_video.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="am_map.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_englsh.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_event.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_items.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_iwad.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_loop.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_mode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_player.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_textur.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_think.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d_ticcmd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deh_main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deh_misc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="deh_str.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doom.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomdata.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomdef.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomfeatures.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomkeys.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomstat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dstrings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="f_finale.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="f_wipe.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="g_game.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gusconf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hu_lib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hu_stuff.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_cdmus.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_endoom.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_joystick.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_scale.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_sound.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_swap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_system.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="i_video.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="info.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_argv.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_bbox.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_cheat.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_controls.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_fixed.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_menu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_misc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="m_random.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="memio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_client.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_dedicated.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_defs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_gui.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_io.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_loop.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_packet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_query.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_sdl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="net_server.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_inter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_local.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_mobj.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_pspr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_saveg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_setup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_spec.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="p_tick.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_bsp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_data.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_defs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_draw.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_local.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_plane.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_segs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_sky.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_state.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="r_things.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="s_sound.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sha1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sounds.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="st_lib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="st_stuff.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="statdump.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tables.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="v_patch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="v_video.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="w_checksum.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="w_file.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="w_main.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="w_merge.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="w_wad.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wi_stuff.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="z_zone.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="doomgeneric.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,450 +0,0 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include "libc/syscall.h"
|
||||
#include "libc/libui.h"
|
||||
#include "libc/stdlib.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MD_MAX_CONTENT 16384
|
||||
#define MD_MAX_LINES 256
|
||||
#define MD_CHAR_WIDTH 8
|
||||
#define MD_LINE_HEIGHT 16
|
||||
|
||||
#define COLOR_DARK_PANEL 0xFF202020
|
||||
#define COLOR_DARK_BG 0xFF121212
|
||||
#define COLOR_DARK_TEXT 0xFFE0E0E0
|
||||
#define COLOR_DARK_TITLEBAR 0xFF303030
|
||||
#define COLOR_BLACK 0xFF000000
|
||||
|
||||
typedef enum {
|
||||
MD_LINE_NORMAL,
|
||||
MD_LINE_HEADING1,
|
||||
MD_LINE_HEADING2,
|
||||
MD_LINE_HEADING3,
|
||||
MD_LINE_BOLD,
|
||||
MD_LINE_ITALIC,
|
||||
MD_LINE_LIST,
|
||||
MD_LINE_BLOCKQUOTE,
|
||||
MD_LINE_CODE
|
||||
} MDLineType;
|
||||
|
||||
typedef struct {
|
||||
char content[256];
|
||||
int length;
|
||||
MDLineType type;
|
||||
int indent_level;
|
||||
} MDLine;
|
||||
|
||||
static MDLine lines[MD_MAX_LINES];
|
||||
static int line_count = 0;
|
||||
static int scroll_top = 0;
|
||||
static char open_filename[256] = "";
|
||||
|
||||
static int win_w = 600;
|
||||
static int win_h = 400;
|
||||
|
||||
static size_t md_strlen(const char *str) {
|
||||
size_t len = 0;
|
||||
while (str[len]) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void md_strcpy(char *dest, const char *src) {
|
||||
while (*src) *dest++ = *src++;
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
static int md_strncpy(char *dest, const char *src, int n) {
|
||||
int i = 0;
|
||||
while (i < n && src[i]) {
|
||||
dest[i] = src[i];
|
||||
i++;
|
||||
}
|
||||
dest[i] = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
static void md_parse_line(const char *raw_line, char *output, MDLineType *type, int *indent) {
|
||||
int i = 0;
|
||||
int out_idx = 0;
|
||||
*indent = 0;
|
||||
*type = MD_LINE_NORMAL;
|
||||
|
||||
while (raw_line[i] == ' ' || raw_line[i] == '\t') {
|
||||
if (raw_line[i] == '\t') *indent += 2;
|
||||
else *indent += 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (raw_line[i] == '#') {
|
||||
int hash_count = 0;
|
||||
while (raw_line[i] == '#') {
|
||||
hash_count++;
|
||||
i++;
|
||||
}
|
||||
if (raw_line[i] == ' ') i++;
|
||||
|
||||
if (hash_count == 1) *type = MD_LINE_HEADING1;
|
||||
else if (hash_count == 2) *type = MD_LINE_HEADING2;
|
||||
else if (hash_count <= 6) *type = MD_LINE_HEADING3;
|
||||
} else if (raw_line[i] == '-' || raw_line[i] == '*') {
|
||||
if ((raw_line[i] == '-' || raw_line[i] == '*') && (raw_line[i+1] == ' ' || raw_line[i+1] == '\t')) {
|
||||
*type = MD_LINE_LIST;
|
||||
i += 2;
|
||||
while (raw_line[i] == ' ' || raw_line[i] == '\t') i++;
|
||||
}
|
||||
} else if (raw_line[i] == '>') {
|
||||
*type = MD_LINE_BLOCKQUOTE;
|
||||
i++;
|
||||
if (raw_line[i] == ' ') i++;
|
||||
}
|
||||
|
||||
while (raw_line[i] && out_idx < 255) {
|
||||
if (raw_line[i] == '*' && raw_line[i+1] == '*') {
|
||||
i += 2;
|
||||
while (raw_line[i] && !(raw_line[i] == '*' && raw_line[i+1] == '*') && out_idx < 255) {
|
||||
output[out_idx++] = raw_line[i++];
|
||||
}
|
||||
if (raw_line[i] == '*' && raw_line[i+1] == '*') i += 2;
|
||||
continue;
|
||||
}
|
||||
if ((raw_line[i] == '*' || raw_line[i] == '_') && out_idx > 0 && raw_line[i-1] != '\\') {
|
||||
char delim = raw_line[i];
|
||||
i++;
|
||||
while (raw_line[i] && raw_line[i] != delim && out_idx < 255) {
|
||||
output[out_idx++] = raw_line[i++];
|
||||
}
|
||||
if (raw_line[i] == delim) i++;
|
||||
continue;
|
||||
}
|
||||
if (raw_line[i] == '`') {
|
||||
i++;
|
||||
while (raw_line[i] && raw_line[i] != '`' && out_idx < 255) {
|
||||
output[out_idx++] = raw_line[i++];
|
||||
}
|
||||
if (raw_line[i] == '`') i++;
|
||||
continue;
|
||||
}
|
||||
if (raw_line[i] == '[') {
|
||||
i++;
|
||||
while (raw_line[i] && raw_line[i] != ']' && out_idx < 255) {
|
||||
output[out_idx++] = raw_line[i++];
|
||||
}
|
||||
if (raw_line[i] == ']') i++;
|
||||
if (raw_line[i] == '(') {
|
||||
while (raw_line[i] && raw_line[i] != ')') i++;
|
||||
if (raw_line[i] == ')') i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
output[out_idx++] = raw_line[i++];
|
||||
}
|
||||
output[out_idx] = 0;
|
||||
}
|
||||
|
||||
static void md_clear_all(void) {
|
||||
for (int i = 0; i < MD_MAX_LINES; i++) {
|
||||
lines[i].content[0] = 0;
|
||||
lines[i].length = 0;
|
||||
lines[i].type = MD_LINE_NORMAL;
|
||||
lines[i].indent_level = 0;
|
||||
}
|
||||
line_count = 0;
|
||||
scroll_top = 0;
|
||||
open_filename[0] = 0;
|
||||
}
|
||||
|
||||
void markdown_open_file(const char *filename) {
|
||||
md_clear_all();
|
||||
md_strcpy(open_filename, filename);
|
||||
|
||||
int fd = sys_open(filename, "r");
|
||||
if (fd < 0) return;
|
||||
|
||||
static char buffer[MD_MAX_CONTENT];
|
||||
int bytes_read = sys_read(fd, buffer, sizeof(buffer) - 1);
|
||||
sys_close(fd);
|
||||
|
||||
if (bytes_read <= 0) return;
|
||||
buffer[bytes_read] = 0;
|
||||
|
||||
int line = 0;
|
||||
int col = 0;
|
||||
char raw_line[256] = "";
|
||||
bool in_code_block = false;
|
||||
|
||||
for (int i = 0; i < bytes_read && line < MD_MAX_LINES; i++) {
|
||||
char ch = buffer[i];
|
||||
if (ch == '\n') {
|
||||
raw_line[col] = 0;
|
||||
if (raw_line[0] == '`' && raw_line[1] == '`' && raw_line[2] == '`') {
|
||||
in_code_block = !in_code_block;
|
||||
} else {
|
||||
if (in_code_block) {
|
||||
md_strcpy(lines[line].content, raw_line);
|
||||
lines[line].length = md_strlen(raw_line);
|
||||
lines[line].type = MD_LINE_CODE;
|
||||
lines[line].indent_level = 0;
|
||||
line++;
|
||||
} else {
|
||||
char parsed_content[256];
|
||||
MDLineType type;
|
||||
int indent;
|
||||
md_parse_line(raw_line, parsed_content, &type, &indent);
|
||||
md_strcpy(lines[line].content, parsed_content);
|
||||
lines[line].length = md_strlen(parsed_content);
|
||||
lines[line].type = type;
|
||||
lines[line].indent_level = indent;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
col = 0;
|
||||
raw_line[0] = 0;
|
||||
} else if (col < 255) {
|
||||
raw_line[col++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (col > 0 && line < MD_MAX_LINES) {
|
||||
raw_line[col] = 0;
|
||||
if (raw_line[0] == '`' && raw_line[1] == '`' && raw_line[2] == '`') {
|
||||
} else if (in_code_block) {
|
||||
md_strcpy(lines[line].content, raw_line);
|
||||
lines[line].length = md_strlen(raw_line);
|
||||
lines[line].type = MD_LINE_CODE;
|
||||
lines[line].indent_level = 0;
|
||||
line++;
|
||||
} else {
|
||||
char parsed_content[256];
|
||||
MDLineType type;
|
||||
int indent;
|
||||
md_parse_line(raw_line, parsed_content, &type, &indent);
|
||||
md_strcpy(lines[line].content, parsed_content);
|
||||
lines[line].length = md_strlen(parsed_content);
|
||||
lines[line].type = type;
|
||||
lines[line].indent_level = indent;
|
||||
line++;
|
||||
}
|
||||
}
|
||||
line_count = line;
|
||||
}
|
||||
|
||||
static void md_draw_text_bold(ui_window_t win, int x, int y, const char *text, uint32_t color) {
|
||||
ui_draw_string(win, x, y, text, color);
|
||||
ui_draw_string(win, x + 1, y, text, color);
|
||||
}
|
||||
|
||||
static void md_paint(ui_window_t win) {
|
||||
int offset_x = 4;
|
||||
int offset_y = 0;
|
||||
int content_width = win_w - 8;
|
||||
int content_height = win_h - 28;
|
||||
|
||||
ui_draw_rounded_rect_filled(win, offset_x, offset_y, content_width, 20, 6, COLOR_DARK_PANEL);
|
||||
ui_draw_string(win, offset_x + 4, offset_y + 4, "File", COLOR_DARK_TEXT);
|
||||
ui_draw_string(win, offset_x + 50, offset_y + 4, open_filename, COLOR_DARK_TEXT);
|
||||
|
||||
int btn_x_up = offset_x + content_width - 50;
|
||||
int btn_y = offset_y + 2;
|
||||
ui_draw_rounded_rect_filled(win, btn_x_up, btn_y, 20, 16, 4, COLOR_DARK_TITLEBAR);
|
||||
ui_draw_string(win, btn_x_up + 6, btn_y, "^", COLOR_DARK_TEXT);
|
||||
ui_draw_rounded_rect_filled(win, btn_x_up + 24, btn_y, 20, 16, 4, COLOR_DARK_TITLEBAR);
|
||||
ui_draw_string(win, btn_x_up + 30, btn_y, "v", COLOR_DARK_TEXT);
|
||||
|
||||
int content_start_y = offset_y + 24;
|
||||
int content_start_x = offset_x + 4;
|
||||
int usable_content_width = content_width - 8 - 20;
|
||||
int usable_content_height = content_height - 28;
|
||||
int max_display_lines = usable_content_height / MD_LINE_HEIGHT;
|
||||
|
||||
ui_draw_rounded_rect_filled(win, 4, content_start_y, win_w - 24, usable_content_height, 6, COLOR_DARK_BG);
|
||||
|
||||
int display_line = 0;
|
||||
int i = scroll_top;
|
||||
|
||||
while (i < line_count && display_line < max_display_lines) {
|
||||
MDLine *line = &lines[i];
|
||||
|
||||
int line_height = MD_LINE_HEIGHT;
|
||||
int extra_spacing = 0;
|
||||
uint32_t text_color = COLOR_DARK_TEXT;
|
||||
bool use_bold = false;
|
||||
|
||||
switch (line->type) {
|
||||
case MD_LINE_HEADING1:
|
||||
line_height = MD_LINE_HEIGHT * 2;
|
||||
text_color = 0xFF87CEEB;
|
||||
use_bold = true;
|
||||
extra_spacing = 4;
|
||||
break;
|
||||
case MD_LINE_HEADING2:
|
||||
line_height = MD_LINE_HEIGHT + 6;
|
||||
text_color = 0xFF4A90E2;
|
||||
use_bold = true;
|
||||
extra_spacing = 2;
|
||||
break;
|
||||
case MD_LINE_HEADING3:
|
||||
line_height = MD_LINE_HEIGHT + 2;
|
||||
text_color = 0xFF87CEEB;
|
||||
use_bold = false;
|
||||
break;
|
||||
case MD_LINE_BLOCKQUOTE:
|
||||
text_color = 0xFFA0A0A0;
|
||||
break;
|
||||
case MD_LINE_CODE:
|
||||
text_color = 0xFF90EE90;
|
||||
break;
|
||||
default:
|
||||
text_color = COLOR_DARK_TEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (display_line + (line_height / MD_LINE_HEIGHT) > max_display_lines) break;
|
||||
|
||||
int x_offset = content_start_x + (line->indent_level * 4);
|
||||
int available_width = usable_content_width - (line->indent_level * 4);
|
||||
int max_chars_per_line = available_width / MD_CHAR_WIDTH;
|
||||
if (max_chars_per_line < 1) max_chars_per_line = 1;
|
||||
|
||||
const char *text = line->content;
|
||||
int text_len = line->length;
|
||||
int char_idx = 0;
|
||||
int local_display_line = 0;
|
||||
int wrapped_line_count = 0;
|
||||
|
||||
while (char_idx < text_len || (text_len == 0 && local_display_line == 0)) {
|
||||
int line_y = content_start_y + display_line * MD_LINE_HEIGHT + (local_display_line * MD_LINE_HEIGHT);
|
||||
|
||||
char line_segment[256];
|
||||
int segment_len = 0;
|
||||
int segment_start = char_idx;
|
||||
|
||||
while (char_idx < text_len && segment_len < max_chars_per_line) {
|
||||
line_segment[segment_len++] = text[char_idx++];
|
||||
}
|
||||
line_segment[segment_len] = 0;
|
||||
|
||||
if (char_idx < text_len && segment_len > 0) {
|
||||
int last_space = -1;
|
||||
for (int j = segment_len - 1; j >= 0; j--) {
|
||||
if (line_segment[j] == ' ') {
|
||||
last_space = j; break;
|
||||
}
|
||||
}
|
||||
if (last_space > 0) {
|
||||
segment_len = last_space;
|
||||
line_segment[segment_len] = 0;
|
||||
char_idx = segment_start + last_space + 1;
|
||||
while (char_idx < text_len && text[char_idx] == ' ') char_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (line->type == MD_LINE_CODE && segment_len > 0) {
|
||||
ui_draw_rect(win, x_offset - 2, line_y - 2, (segment_len * MD_CHAR_WIDTH) + 4, 12, COLOR_BLACK);
|
||||
}
|
||||
|
||||
if (local_display_line == 0) {
|
||||
switch (line->type) {
|
||||
case MD_LINE_LIST:
|
||||
ui_draw_rect(win, x_offset, line_y + MD_LINE_HEIGHT/2 - 1, 2, 2, COLOR_BLACK);
|
||||
x_offset += 12;
|
||||
if (segment_len > 0 && line_segment[0] == ' ') {
|
||||
for (int j = 0; j < segment_len - 1; j++) line_segment[j] = line_segment[j + 1];
|
||||
segment_len--;
|
||||
}
|
||||
break;
|
||||
case MD_LINE_BLOCKQUOTE:
|
||||
ui_draw_rect(win, x_offset - 4, line_y, 2, line_height, 0xFF404080);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (segment_len > 0) {
|
||||
if (use_bold) {
|
||||
md_draw_text_bold(win, x_offset, line_y + extra_spacing, line_segment, text_color);
|
||||
} else {
|
||||
ui_draw_string(win, x_offset, line_y, line_segment, text_color);
|
||||
}
|
||||
}
|
||||
|
||||
local_display_line++;
|
||||
wrapped_line_count++;
|
||||
if (char_idx >= text_len) break;
|
||||
}
|
||||
|
||||
display_line += (wrapped_line_count > 0 ? wrapped_line_count : 1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void md_handle_key(char c, bool pressed) {
|
||||
if (!pressed) return;
|
||||
if (c == 'w' || c == 'W' || c == 17) {
|
||||
scroll_top -= 3;
|
||||
if (scroll_top < 0) scroll_top = 0;
|
||||
} else if (c == 's' || c == 'S' || c == 18) {
|
||||
scroll_top += 3;
|
||||
int max_scroll = line_count - 10;
|
||||
if (scroll_top > max_scroll) scroll_top = max_scroll;
|
||||
if (scroll_top < 0) scroll_top = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void md_handle_click(int x, int y) {
|
||||
int content_width = win_w - 8;
|
||||
int btn_x_up = 4 + content_width - 50;
|
||||
int btn_y = 2;
|
||||
if (x >= btn_x_up && x < btn_x_up + 20 && y >= btn_y && y < btn_y + 16) {
|
||||
scroll_top -= 3;
|
||||
if (scroll_top < 0) scroll_top = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int btn_x_down_top = 4 + content_width - 50 + 24;
|
||||
if (x >= btn_x_down_top && x < btn_x_down_top + 20 && y >= btn_y && y < btn_y + 16) {
|
||||
scroll_top += 3;
|
||||
int max_scroll = line_count - 10;
|
||||
if (scroll_top > max_scroll) scroll_top = max_scroll;
|
||||
if (scroll_top < 0) scroll_top = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ui_window_t win = ui_window_create("Markdown Viewer", 150, 180, win_w, win_h);
|
||||
if (!win) return 1;
|
||||
|
||||
md_clear_all();
|
||||
if (argc > 1) {
|
||||
markdown_open_file(argv[1]);
|
||||
}
|
||||
|
||||
gui_event_t ev;
|
||||
while (1) {
|
||||
if (ui_get_event(win, &ev)) {
|
||||
if (ev.type == GUI_EVENT_PAINT) {
|
||||
md_paint(win);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
} else if (ev.type == GUI_EVENT_CLICK) {
|
||||
md_handle_click(ev.arg1, ev.arg2);
|
||||
md_paint(win);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
} else if (ev.type == GUI_EVENT_KEY) {
|
||||
md_handle_key((char)ev.arg1, true);
|
||||
md_paint(win);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
} else if (ev.type == GUI_EVENT_KEYUP) {
|
||||
md_handle_key((char)ev.arg1, false);
|
||||
} else if (ev.type == GUI_EVENT_CLOSE) {
|
||||
sys_exit(0);
|
||||
}
|
||||
} else {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "stdlib.h"
|
||||
#include "libui.h"
|
||||
#include "syscall_user.h"
|
||||
|
||||
#define STBI_WRITE_NO_STDIO
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
#include <string.h>
|
||||
|
||||
#define GUI_CMD_GET_SCREEN_SIZE 17
|
||||
#define GUI_CMD_GET_SCREENBUFFER 18
|
||||
#define GUI_CMD_SHOW_NOTIFICATION 19
|
||||
#define GUI_CMD_GET_DATETIME 20
|
||||
|
||||
void png_write_func(void *context, void *data, int size) {
|
||||
int fd = *(int*)context;
|
||||
sys_write_fs(fd, data, size);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
// 1. Get screen size
|
||||
uint64_t w = 0, h = 0;
|
||||
syscall3(SYS_GUI, GUI_CMD_GET_SCREEN_SIZE, (uint64_t)&w, (uint64_t)&h);
|
||||
|
||||
if (w == 0 || h == 0 || w > 4096 || h > 4096) {
|
||||
printf("Failed to get screen size %d x %d\n", (int)w, (int)h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 2. Allocate buffer for 0xAARRGGBB
|
||||
uint32_t *pixels = (uint32_t *)malloc(w * h * sizeof(uint32_t));
|
||||
if (!pixels) {
|
||||
printf("Failed to allocate memory for %d x %d pixels\n", (int)w, (int)h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 3. Request screenbuffer
|
||||
syscall2(SYS_GUI, GUI_CMD_GET_SCREENBUFFER, (uint64_t)pixels);
|
||||
|
||||
// 4. Convert 0xAARRGGBB to RGB for stb_image_write
|
||||
uint8_t *rgb_pixels = (uint8_t *)malloc(w * h * 3);
|
||||
if (!rgb_pixels) {
|
||||
printf("Failed to allocate RGB buffer\n");
|
||||
free(pixels);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int y = 0; y < (int)h; y++) {
|
||||
for (int x = 0; x < (int)w; x++) {
|
||||
uint32_t px = pixels[y * w + x];
|
||||
int idx = (y * w + x) * 3;
|
||||
rgb_pixels[idx + 0] = (px >> 16) & 0xFF; // R
|
||||
rgb_pixels[idx + 1] = (px >> 8) & 0xFF; // G
|
||||
rgb_pixels[idx + 2] = (px) & 0xFF; // B
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Get Datetime for filename
|
||||
uint64_t dt[6] = {0};
|
||||
syscall2(SYS_GUI, GUI_CMD_GET_DATETIME, (uint64_t)dt);
|
||||
|
||||
char filename[128] = "A:/Desktop/screenshot-";
|
||||
|
||||
// Quick helper to append 4-digit and 2-digit numbers
|
||||
auto void append_num(int num, int digits);
|
||||
void append_num(int num, int digits) {
|
||||
int len = 0; while (filename[len]) len++;
|
||||
if (digits == 4) {
|
||||
filename[len++] = '0' + (num / 1000) % 10;
|
||||
filename[len++] = '0' + (num / 100) % 10;
|
||||
}
|
||||
filename[len++] = '0' + (num / 10) % 10;
|
||||
filename[len++] = '0' + (num % 10);
|
||||
filename[len] = '\0';
|
||||
}
|
||||
|
||||
append_num((int)dt[0], 4);
|
||||
append_num((int)dt[1], 2);
|
||||
append_num((int)dt[2], 2);
|
||||
int len = 0; while (filename[len]) len++;
|
||||
filename[len++] = '-'; filename[len] = '\0';
|
||||
append_num((int)dt[3], 2);
|
||||
append_num((int)dt[4], 2);
|
||||
append_num((int)dt[5], 2);
|
||||
len = 0; while (filename[len]) len++;
|
||||
filename[len++] = '.'; filename[len++] = 'p'; filename[len++] = 'n'; filename[len++] = 'g'; filename[len] = '\0';
|
||||
|
||||
// 6. Write to PNG
|
||||
int fd = sys_open(filename, "w"); // Open file
|
||||
int res = 0;
|
||||
if (fd >= 0) {
|
||||
res = stbi_write_png_to_func(png_write_func, &fd, (int)w, (int)h, 3, rgb_pixels, (int)w * 3);
|
||||
sys_close(fd); // Close file
|
||||
}
|
||||
|
||||
free(rgb_pixels);
|
||||
free(pixels);
|
||||
|
||||
if (res) {
|
||||
char notif[256] = "Saved ";
|
||||
int nlen = 6;
|
||||
int flen = 0;
|
||||
while (filename[11 + flen]) {
|
||||
notif[nlen + flen] = filename[11 + flen];
|
||||
flen++;
|
||||
}
|
||||
notif[nlen + flen] = '\0';
|
||||
|
||||
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)notif);
|
||||
} else {
|
||||
syscall2(SYS_GUI, GUI_CMD_SHOW_NOTIFICATION, (uint64_t)"Failed to save screenshot");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
||||
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
||||
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
||||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
static void beep(int freq, int ms) {
|
||||
sys_system(14, freq, ms, 0, 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Playing Sweden - C418 (Minecraft)...\n");
|
||||
|
||||
// Main melody (simplified pattern)
|
||||
beep(392, 400); // G4
|
||||
beep(440, 400); // A4
|
||||
beep(493, 800); // B4
|
||||
|
||||
beep(440, 400); // A4
|
||||
beep(392, 800); // G4
|
||||
beep(329, 800); // E4
|
||||
|
||||
beep(392, 400); // G4
|
||||
beep(440, 400); // A4
|
||||
beep(493, 800); // B4
|
||||
|
||||
beep(440, 400); // A4
|
||||
beep(392, 1200); // G4
|
||||
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <stdint.h>
|
||||
#include "limine.h"
|
||||
#include "platform.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
// --- Internal State ---
|
||||
// memory_pool is no longer a single pointer, as we now manage multiple regions.
|
||||
@@ -16,6 +17,7 @@ static size_t total_allocated = 0;
|
||||
static size_t peak_allocated = 0;
|
||||
static uint32_t allocation_counter = 0;
|
||||
static bool initialized = false;
|
||||
static spinlock_t mm_lock = SPINLOCK_INIT;
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
extern void serial_write_num(uint32_t n);
|
||||
@@ -174,8 +176,7 @@ static void remove_block_at(int idx) {
|
||||
void* kmalloc_aligned(size_t size, size_t alignment) {
|
||||
if (!initialized || size == 0) return NULL;
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&mm_lock);
|
||||
|
||||
if (alignment == 0) alignment = 8;
|
||||
size = (size + 7) & ~7ULL; // Ensure size is multiple of 8
|
||||
@@ -245,12 +246,12 @@ void* kmalloc_aligned(size_t size, size_t alignment) {
|
||||
if (total_allocated > peak_allocated) peak_allocated = total_allocated;
|
||||
|
||||
mem_memset(ptr, 0, size);
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&mm_lock, rflags);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&mm_lock, rflags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -261,8 +262,7 @@ void* kmalloc(size_t size) {
|
||||
void kfree(void *ptr) {
|
||||
if (ptr == NULL || !initialized) return;
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&mm_lock);
|
||||
|
||||
int block_idx = -1;
|
||||
for (int i = 0; i < block_count; i++) {
|
||||
@@ -273,7 +273,7 @@ void kfree(void *ptr) {
|
||||
}
|
||||
|
||||
if (block_idx == -1) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&mm_lock, rflags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ void kfree(void *ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
spinlock_release_irqrestore(&mm_lock, rflags);
|
||||
}
|
||||
|
||||
void* krealloc(void *ptr, size_t new_size) {
|
||||