Hướng dẫn Thiết lập Dự án Game Boy Advance với Rust và Thư viện gba 0.11.5

Thư viện gba phiên bản 0.11.5 là một crate Rust hỗ trợ phát triển phần mềm nhúng cho nền tảng Game Boy Advance (GBA). Đây là một thư viện không phụ thuộc vào tiêu chuẩn runtime của Rust (no_std), được tối ưu hóa cho kiến trúc ARM7TDMI với tập lệnh Thumb-1 và môi trường không có hệ điều hành.

Yêu cầu bắt buộc

  • Rust Nightly: Phiên bản ổn định không đủ — cần sử dụng rustup để thiết lập kênh nightly làm mặc định:
rustup default nightly
  • Công cụ biên dịch ARM: Cần cài đặt bộ binutils dành riêng cho ARM, đặc biệt là trình liên kết arm-none-eabi-ld. Trên Linux, có thể cài qua apt, pacman hoặc dnf; trên macOS dùng brew install arm-none-eabi-binutils; trên Windows tải từ trang chủ ARM hoặc dùng MSYS2.
  • Mã nguồn Rust: Thực thi lệnh sau để tải mã nguồn lõi (core) — cần thiết khi build lại thư viện chuẩn cho target GBA:
rustup component add rust-src

Cấu hình Cargo

Tạo tệp .cargo/config.toml trong thư mục gốc dự án với nội dung sau:

[build]
target = "thumbv4t-none-eabi"

[unstable]
build-std = ["core"]

[target.thumbv4t-none-eabi]
runner = "mgba-qt"
rustflags = [
  "-Clink-arg=-Tlinker_scripts/mono_boot.ld",
  "-Clink-arg=--nmagic"
]

Khai báo điểm vào chương trình

Mỗi tệp thực thi (binary hoặc example) phải khai báo rõ ràng các thuộc tính bắt buộc:

  • #![no_std]: Vô hiệu hóa thư viện chuẩn Rust.
  • #![no_main]: Tắt hàm main mặc định của Rust runtime.
  • Một hàm xử lý panic tùy chỉnh.
  • Hàm main được xuất dưới ABI C, không đổi tên (no_mangle), trả về kiểu ! (never type).

Ví dụ mẫu:

#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[panic_handler]
fn handle_panic(_info: &PanicInfo) -> ! {
  loop {}
}

#[no_mangle]
pub extern "C" fn main() -> ! {
  // Khởi tạo phần cứng, vòng lặp trò chơi, v.v.
  loop {
    // Đọc phím, cập nhật trạng thái, vẽ khung hình...
  }
}

Xuất file thực thi cho GBA

Cargo tạo ra tệp ELF — phù hợp để chạy trên trình giả lập như mgba-qt. Để chạy trên phần cứng thật, cần chuyển đổi sang định dạng ROM:

  1. Dùng arm-none-eabi-objcopy để trích xuất phần code/data thành binary thuần:
arm-none-eabi-objcopy -O binary target/thumbv4t-none-eabi/debug/my_game my_game.bin
  1. Sử dụng gbafix để thêm header GBA chuẩn (đảm bảo checksum và thông tin tiêu đề đúng):
cargo install gbafix
gbafix my_game.bin -o my_game.gba

So sánh với các crate khác

Thư viện gba tập trung vào tính an toàn và kiểm soát tường minh qua ownership. Nếu bạn cần API cấp cao hơn với khả năng quản lý tài nguyên linh hoạt hơn (ví dụ: chia sẻ an toàn giữa nhiều module phần cứng), hãy cân nhắc agb — một crate thay thế được thiết kế theo hướng "zero-cost abstractions" và tích hợp mạnh với borrow checker.

Target hỗ trợ

Thư viện được kiểm thử trên hai target chính:

  • thumbv4t-none-eabi — target chính, sử dụng chế độ Thumb-1 với hỗ trợ nhân BIOS.
  • armv4t-none-eabi — ít phổ biến hơn, dùng tập lệnh ARM đầy đủ (không khuyến khích trừ khi cần tối ưu đặc biệt).

Các module chính

Module Mô tả
asm_runtimeCung cấp mã assembly khởi tạo stack, vector table và chuyển quyền điều khiển tới Rust.
biosGói hàm gọi BIOS GBA như swi_wait_for_vblank, swi_cpy.
dmaĐiều khiển các kênh DMA 0–3 để sao chép dữ liệu nhanh giữa RAM, VRAM, OAM.
gba_cellLoại GbaCell<T> cho phép chia sẻ dữ liệu thay đổi toàn cục một cách an toàn mà không cần unsafe.
keysĐọc trạng thái nút bấm qua thanh ghi KEYINPUT và hỗ trợ debounce.
mmioĐịnh nghĩa tất cả địa chỉ bộ nhớ ánh xạ vào (MMIO) như DISPCNT, TM0CNT, SOUND_CNT_X.
timersAPI để cấu hình và sử dụng 4 bộ đếm thời gian phần cứng (Timer 0–3).
videoĐiều khiển màn hình: thiết lập mode hiển thị, quản lý background, sprite và palette.

Macro và kiểu dữ liệu quan trọng

  • include_aligned_bytes!: Tương tự include_bytes!, nhưng đảm bảo dữ liệu được căn lề 4-byte — yêu cầu bắt buộc với texture, tilemap và nhạc PCM trên GBA.
  • Align4<T>: Bao bọc kiểu T để đảm bảo vùng nhớ luôn bắt đầu tại địa chỉ chia hết cho 4 — cần thiết cho DMA và BIOS copy.

Thẻ: Rust game-boy-advance embedded-rust thumbv4t gbadev

Đăng vào ngày 26 tháng 5 lúc 22:53