DEV Community

Cover image for From Python Code to a Bootable Graphics OS
Divyanshu Sinha
Divyanshu Sinha

Posted on

From Python Code to a Bootable Graphics OS

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.

Watch the Graphics Demo

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")
Enter fullscreen mode Exit fullscreen mode

Getting Started

Install Aetherix:

pip install aetherix
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
divyanshusinha136 profile image
Divyanshu Sinha • Edited

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.