
Здравствуйте, уважаемые читатели!
В этой статье я хотел бы поделиться необычным и вдохновляющим проектом — реализацией арканоида в текстовом VGA-режиме, написанного полностью на Rust, без использования стандартной библиотеки и даже без аллокации памяти (#![no_std] + no_alloc).
Проект работает напрямую с VGA-памятью и PS/2 клавиатурой через порт 0x60, создавая абсолютно нативную игру в стиле 80-х, но с современным вниманием к качеству кода. И всё это — с участием милого талисмана Platinum-tan.
Зачем вообще создавать игру в текстовом режиме?
Для нас, разработчиков, работающих с высокоуровневыми фреймворками и богатыми API, подобные проекты становятся отличной возможностью:
Погрузиться в низкоуровневую архитектуру x86
Попрактиковаться в чистой архитектуре и системном программировании
Понять, как можно обойтись без аллокации, без стандартных зависимостей
И просто — почувствовать дух ретро
Архитектура проекта
Проект написан на Rust с использованием #![no_std] и bootimage, что позволяет компилировать игру в виде загрузочного ядра.
Основные модули:
Модуль | Назначение |
|---|---|
| Прямая работа с VGA-буфером |
| Чтение клавиш напрямую с |
| Игровая логика, отрисовка, физика мячика |
Точка входа, игровой цикл, обработка клавиш |
Особенности реализации
Мячик (
o) отскакивает от стен, блоков и платформыПлатформа (
=======) управляется клавишамиAиDЦвета блоков зависят от строки (радуга в ASCII)
Поддержка
SPACEдля начала иRдля рестартаВывод очков и милых сообщений от Platinum-tan
Немного магии: как работают цвета
ColorCode::new(Color::Red, Color::Black)
Каждый символ в VGA-буфере имеет не только ASCII-байт, но и байт цвета. Мы изменяем эти цвета на лету — и получаем полноцветный «текстовый» арканоид.
Чтение клавиш без драйвера
pub unsafe fn inb(port: u16) -> u8 { let value: u8; core::arch::asm!(\"in al, dx\", out(\"al\") value, in(\"dx\") port); value }
Клавиши считываются напрямую из порта 0x60 — без драйверов, без ОС, просто железо и вы.
Вывод информации в виртуальную машину кастомный и реализован через vga_buffer так как мы не можем использовать вывод с использованием no_std
... impl Writer { pub fn new() -> Self { Self { column_position: 0, color_code: ColorCode::new(Color::Yellow, Color::Black), buffer: unsafe { &mut *(VGA_BUFFER_ADDR as *mut Buffer) }, } } pub fn write_byte(&mut self, byte: u8) { match byte { b'\n' => self.new_line(), byte => { if self.column_position >= BUFFER_WIDTH { self.new_line(); } let row = BUFFER_HEIGHT - 1; let col = self.column_position; self.buffer.chars[row][col].write(ScreenChar { ascii_character: byte, color_code: self.color_code, }); self.column_position += 1; } } } pub fn write_string(&mut self, s: &str) { for byte in s.bytes() { match byte { 0x20..=0x7e | b'\n' => self.write_byte(byte), _ => self.write_byte(0xfe), } } } pub fn new_line(&mut self) { for row in 1..BUFFER_HEIGHT { for col in 0..BUFFER_WIDTH { let c = self.buffer.chars[row][col].read(); self.buffer.chars[row - 1][col].write(c); } } self.clear_row(BUFFER_HEIGHT - 1); self.column_position = 0; } fn clear_row(&mut self, row: usize) { let blank = ScreenChar { ascii_character: b' ', color_code: self.color_code, }; for col in 0..BUFFER_WIDTH { self.buffer.chars[row][col].write(blank); } } /// Выводит строку по центру последней строки экрана pub fn write_centered(&mut self, text: &str) { let len = text.len().min(BUFFER_WIDTH); let padding = (BUFFER_WIDTH - len) / 2; self.column_position = padding; self.write_string(text); } ...
Как собрать и запустить
Установите Rust nightly и bootimage:
rustup install nightly rustup component add rust-src --toolchain nightly cargo install bootimage
Соберите ядро:
cargo +nightly bootimage -Z build-std=core,compiler_builtins --target x86_64-platinum_os.json -Z build-std-features=compiler-builtins-mem --target-dir target/x86_64-platinum_os
Запустите в QEMU:
qemu-system-x86_64 -drive format=raw,file=target\x86_64-platinum_os\x86_64-platinum_os\debug\bootimage-platinum_os.bin -serial stdio -no-reboot -no-shutdown
Демо: Скриншот

Вдохновение
Это не просто технический эксперимент — это способ выразить любовь к железу, к языку Rust, и к эстетике ASCII-графики. Если вы когда-нибудь мечтали создать свою игру без ОС — сейчас самое время.
Спасибо за внимание!
