One of the classic milestones in hobby operating system development is switching from text mode to graphics mode. In this example, Aetherix boots into VGA Mode 13h, plays a loading animation, renders a full-screen background, and composites a logo all from Python code that builds a bootable disk image.
Highlights
- 🎞️ Loading animation
- 🎨 VGA Mode 13h graphics
- 🖼️ Full-screen background rendering
- 🪟 Logo compositing
- 💾 Bootable disk image generation
- 🐍 Written in Python with Aetherix
The example preprocesses images at build time, generating a shared VGA palette for the background and logo. When the system boots, the kernel simply renders the prepared pixel data, resulting in a fast graphical startup.
Source code
from os import system as s
from pathlib import Path
from aetherix import Project, imaging
from aetherix.drivers import graphics
ASSETS_DIR = Path(__file__).resolve().parent / "assets"
# -- Prepare assets at build time (resizing/quantizing happens here, not
# at boot -- the kernel only ever handles already-prepared bytes) --
loading_frames = [
imaging.load_image(ASSETS_DIR / f"loading_{i}.png") for i in range(6)
]
# background and logo will be on screen AT THE SAME TIME, so they must
# share one 256-color palette -- VGA Mode 13h has a single palette for the
# whole screen, not one per image (see imaging.load_images_shared_palette).
background, logo = imaging.load_images_shared_palette([
(ASSETS_DIR / "background.png", graphics.GFX_WIDTH, graphics.GFX_HEIGHT, True),
(ASSETS_DIR / "logo.png", 64, 64, False),
])
LOGO_X = (graphics.GFX_WIDTH - logo.width) // 2
LOGO_Y = (graphics.GFX_HEIGHT - logo.height) // 2
with Project("GraphicsOS", graphics_mode=graphics.MODE_13H) as os_:
@os_.kernel_entry
def main(prog, drivers):
# 1. Loading animation -- plays once, then falls through.
drivers.graphics.play_frames(prog, loading_frames, delay_iterations=3_000_000, loop=False)
# 2. Home screen -- background, then a logo composited on top.
drivers.graphics.show_image(prog, background, x=0, y=0)
drivers.graphics.show_image(prog, logo, x=LOGO_X, y=LOGO_Y)
prog.hlt()
out = os_.build(str("graphics_os.img"))
print(f"Built: {out} ({out.stat().st_size} bytes)")
print(f"Kernel sectors: {(len(os_.kernel.assemble()) + 511) // 512}")
print("Boot it with: qemu-system-i386 -drive file=graphics_os.img,format=raw")
s("qemu-system-i386 -drive file=graphics_os.img,format=raw")
Getting Started
Install Aetherix:
pip install aetherix
Resources
PiPY: https://pypi.org/project/aetherix/
GitHub: https://github.com/DivyanshuSinha136/Aetherix
⭐ If you find Aetherix interesting, consider giving the repository a star on GitHub. Feedback, ideas, and contributions are always welcome!
Top comments (1)
Expected: Hundreds of lines of C and Assembly to switch to graphics mode, prepare assets, and build a bootable disk image.
Reality with Aetherix:
"Wait... that's it?"
🇮🇳 Or, as we'd say in Hindi:
"Bhai, ye to shuru hote hi khatam ho gaya." 😂
That's the idea. Aetherix takes care of the low-level details, so you can focus on building your operating system instead of writing boilerplate.