เกม Game Boy Advance ที่เขียนด้วย Zig
(jonot.me)ทำไมถึงเขียนเกม Game Boy Advance ด้วย Zig
-
เสน่ห์ของ Game Boy Advance
Game Boy Advance มี CPU ที่ค่อนข้างทันสมัย (ARM 32 บิต, รีจิสเตอร์จำนวนมาก) แต่ใช้ตัวเรนเดอร์แบบ tile-based รุ่นเก่า ซึ่งคล้ายกับวิธีที่ NES ใช้ในยุค 80 นับเป็นหนึ่งในระบบแบบ tile-based รุ่นท้าย ๆ ของ Nintendo และรองรับความสามารถหลากหลาย เช่น affine transform, ความโปร่งใส, และเอฟเฟกต์สไปรต์ -
เหตุผลที่เลือกภาษา Zig
ตอนแรกเริ่มโปรเจกต์ Game Boy Advance ด้วย C++ แต่เกมตัวแรกที่ทำเสร็จสมบูรณ์เขียนด้วย Zig แม้ Zig จะยังอยู่ในสถานะเบต้า และเป็นภาษาที่เกิดขึ้นหลังการเปิดตัว Game Boy Advance ราว 15 ปี แต่ก็มีความสามารถที่เหมาะกับการเขียนโปรแกรมแบบ embedded
Toolchain
-
Linux และ devKitPro
ผู้เขียนใช้ Linux และเคยเจอความยุ่งยากด้านการจัดการแพ็กเกจ อีกทั้งตอนทำฉาก 3D สำหรับ Nintendo DS ก็จำเป็นต้องใช้ devKitPro ซึ่งรวม GCC toolchain, ไลบรารี, และเครื่องมือพัฒนาไว้ด้วย แต่ก็มีความยุ่งยากตรงที่ต้องติดตั้งผ่านตัวจัดการแพ็กเกจของ ArchLinux -
ข้อดีของ Zig
Zig ทำ cross-compilation ได้ง่าย และไม่ต้องตั้งค่าตัวจัดการแพ็กเกจที่ซับซ้อน ระบบ build ของ Zig จะทำงานโดยรันฟังก์ชันbuildในไฟล์build.zigเพื่อดำเนินการ build ซึ่งช่วยให้กระบวนการ build เรียบง่ายขึ้นและลดข้อผิดพลาด
Packed Structs
- ความสำคัญของ Packed Structs
Game Boy Advance ควบคุมฮาร์ดแวร์ผ่านรีจิสเตอร์โดยตรง โดยไม่มีการเรียกใช้ API ระดับสูง packed struct ของ Zig ช่วยจัด layout หน่วยความจำให้เหมาะสม จึงทำให้ควบคุมฮาร์ดแวร์ได้ง่ายขึ้น นี่เป็นความสามารถที่มีประโยชน์มากสำหรับการพัฒนาเกมบน Game Boy Advance
Comptime
- การรันโค้ดในช่วงคอมไพล์
Zig มีความสามารถในการรันโค้ดตอน compile time ได้ ทำให้สามารถบีบอัดข้อมูลตั้งแต่ช่วงคอมไพล์ แทนที่จะไปบีบอัดในช่วงรันไทม์ ความสามารถนี้ของ Zig ช่วยให้จัดการการบีบอัดข้อมูลได้ง่ายขึ้น
ไลบรารีมาตรฐาน
- ไลบรารีมาตรฐานที่ยืดหยุ่นของ Zig
ไลบรารีมาตรฐานของ Zig รองรับ generic และให้ฟังก์ชันจัดสรรหน่วยความจำรับ allocator เป็นอาร์กิวเมนต์ได้ ทำให้สามารถใช้วิธีจัดสรรหน่วยความจำแบบกำหนดเองได้ ไลบรารีมาตรฐานของ Zig จึงใช้งานได้อย่างยืดหยุ่นแม้ในสภาพแวดล้อมที่มีข้อจำกัดด้านฮาร์ดแวร์
ปัญหา
-
Inline Assembly
Zig รองรับ inline assembly แต่สามารถมี output ได้เพียงตัวเดียว ซึ่งกลายเป็นปัญหาเมื่อฟังก์ชัน BIOS ของ GBA ต้องส่งออกค่าหลายค่า -
โค้ด Thumb / โค้ด ARM
CPU ของ Game Boy Advance รองรับทั้งโหมด ARM และโหมด Thumb แต่ใน Zig ยังไม่สามารถระบุโหมด ARM และ Thumb ได้อย่างชัดเจน -
หน่วยความจำสุดประหลาด
หน่วยความจำวิดีโอของ Game Boy Advance ไม่สามารถเขียนแบบ 8 บิตได้ และอาจทำให้กราฟิกเพี้ยนได้ Zig จะ optimize การคัดลอกหน่วยความจำด้วยmemcpyแต่สิ่งนี้อาจชนกับ “หน่วยความจำสุดประหลาด” ของ GBA
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
volatileตามเอกสารของ Zig แล้วยังไม่แก้ปัญหา ก็แนะนำให้รายงานบั๊กกับคอมไพเลอร์memcpyเดิมคาดว่า optimization นี้จะเกิดขึ้นเฉพาะใน user space และคาดหวังว่าออปชัน-nostdlibจะจัดการเรื่องนี้โดยอัตโนมัติได้