2 điểm bởi GN⁺ 2025-01-01 | 1 bình luận | Chia sẻ qua WhatsApp

Vì sao lại viết trò chơi Game Boy Advance bằng Zig

  • Sức hấp dẫn của Game Boy Advance
    Game Boy Advance có một CPU hiện đại (ARM 32-bit, nhiều thanh ghi), nhưng lại sử dụng trình kết xuất dựa trên tile kiểu cũ. Cách này tương tự với phương thức mà NES đã dùng từ thập niên 80. Đây là một trong những hệ thống dựa trên tile cuối cùng của Nintendo, đồng thời cung cấp nhiều tính năng như biến đổi affine, độ trong suốt và hiệu ứng sprite.

  • Lý do chọn ngôn ngữ Zig
    Ban đầu dự án Game Boy Advance được khởi động bằng C++, nhưng trò chơi hoàn chỉnh đầu tiên lại được viết bằng Zig. Dù Zig vẫn đang ở bản beta và là ngôn ngữ được tạo ra 15 năm sau khi Game Boy Advance phát hành, nó vẫn cung cấp các tính năng rất phù hợp cho lập trình nhúng.

Chuỗi công cụ

  • Linux và devKitPro
    Khi sử dụng Linux, tác giả gặp khó khăn với việc quản lý gói và từng phải dùng devKitPro khi tạo cảnh 3D cho Nintendo DS. Bộ này bao gồm chuỗi công cụ GCC, thư viện và các công cụ phát triển. Tuy nhiên, việc phải cài đặt qua trình quản lý gói của ArchLinux khá phiền phức.

  • Ưu điểm của Zig
    Zig giúp cross-compile dễ dàng và không cần thiết lập một trình quản lý gói phức tạp. Hệ thống build của Zig thực hiện build bằng cách chạy hàm build trong tệp build.zig. Điều này giúp đơn giản hóa quy trình build và giảm lỗi.

Packed Structs

  • Tầm quan trọng của Packed Structs
    Game Boy Advance điều khiển phần cứng thông qua thanh ghi thay vì các lệnh gọi API cấp cao. packed struct của Zig tối ưu bố cục bộ nhớ để việc điều khiển phần cứng trở nên dễ dàng hơn. Đây là một tính năng đặc biệt hữu ích cho lập trình Game Boy Advance.

Comptime

  • Thực thi mã tại thời điểm biên dịch
    Zig cung cấp khả năng thực thi mã ngay tại thời điểm biên dịch. Nhờ đó, dữ liệu có thể được nén từ lúc biên dịch thay vì phải nén khi chạy. Tính năng này của Zig giúp việc nén dữ liệu trở nên đơn giản hơn.

Thư viện chuẩn

  • Thư viện chuẩn linh hoạt của Zig
    Thư viện chuẩn của Zig hỗ trợ generic và cho phép các hàm cấp phát bộ nhớ nhận memory allocator làm tham số. Điều này cho phép sử dụng các cơ chế cấp phát bộ nhớ tùy biến. Thư viện chuẩn của Zig vì thế vẫn có thể được dùng linh hoạt ngay cả trong môi trường có ràng buộc phần cứng.

Vấn đề

  • Inline assembly
    Zig có hỗ trợ inline assembly, nhưng chỉ cho phép một đầu ra. Điều này gây vấn đề khi các hàm BIOS của GBA cần xuất ra nhiều giá trị.

  • Mã Thumb / mã ARM
    CPU của Game Boy Advance hỗ trợ cả chế độ ARM và chế độ Thumb. Trong Zig, không thể chỉ định tường minh chế độ ARM hay Thumb.

  • Bộ nhớ kỳ lạ
    Bộ nhớ video của Game Boy Advance không thể được ghi theo đơn vị 8-bit, và điều này có thể làm đồ họa bị hỏng. Zig tối ưu khi sao chép bộ nhớ bằng cách dùng memcpy, nhưng điều đó có thể xung đột với “bộ nhớ kỳ lạ” của GBA.

1 bình luận

 
GN⁺ 2025-01-01
Ý kiến Hacker News
  • Cần có cách chỉ định phương thức truy cập bộ nhớ cho các dải địa chỉ cụ thể. Nếu dùng volatile trong tài liệu Zig mà vẫn không giải quyết được thì nên báo cáo lỗi cho trình biên dịch
  • Lý do bắt đầu dùng Linux từ 5 năm trước là vì không biết cách thiết lập Python trên Windows. Trong giai đoạn 1997-2015, Windows là hệ điều hành thống trị, và điều này đã làm tình trạng thiếu kiến thức ở giới trẻ trầm trọng hơn. Thời kỳ đầu, việc truy cập Internet chưa phổ biến, và một hệ điều hành không có môi trường lập trình sẽ khiến người dùng bỏ lỡ cơ hội học lập trình
  • Trên Game Boy Advance, không thể ghi vào bộ nhớ video theo đơn vị 8 bit; làm vậy sẽ khiến đồ họa bị lỗi nặng. Trên trình giả lập thì hoạt động, nhưng trên phần cứng thật mới phát hiện ra vấn đề và phải sửa. Một toolchain GBA cho ngôn ngữ Nim cũng đã được phát triển
  • Đôi khi trình biên dịch thực hiện tối ưu hóa bằng cách thay hàm sao chép bộ nhớ bằng memcpy. Người viết chỉ nghĩ tối ưu hóa này sẽ diễn ra trong không gian người dùng, và đã kỳ vọng tùy chọn -nostdlib có thể tự động xử lý việc này
  • Đề xuất dùng bitfield như một cách sử dụng packed structs trong C. Có đưa ra ví dụ mã C hợp lệ
  • Cần có một cách để giải quyết vấn đề bộ nhớ trên Game Boy Advance. Không rõ LLVM có hỗ trợ tính năng này hay không, nhưng có vẻ việc tích hợp vào Zig sẽ không quá khó