2 คะแนน โดย GN⁺ 2025-01-01 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

ทำไมถึงเขียนเกม 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 ความคิดเห็น

 
GN⁺ 2025-01-01
ความคิดเห็นจาก Hacker News
  • จำเป็นต้องมีวิธีระบุรูปแบบการเข้าถึงหน่วยความจำสำหรับช่วงแอดเดรสเฉพาะ หากใช้ volatile ตามเอกสารของ Zig แล้วยังไม่แก้ปัญหา ก็แนะนำให้รายงานบั๊กกับคอมไพเลอร์
  • เหตุผลที่เริ่มใช้ Linux เมื่อ 5 ปีก่อน คือไม่รู้วิธีตั้งค่า Python บน Windows ช่วงปี 1997-2015 Windows เป็นระบบปฏิบัติการที่ครองตลาด และทำให้ปัญหาการขาดความรู้ในคนรุ่นใหม่รุนแรงขึ้น ในยุคแรกการเข้าถึงอินเทอร์เน็ตยังไม่แพร่หลาย และระบบปฏิบัติการที่ไม่มีสภาพแวดล้อมสำหรับเขียนโปรแกรมก็ทำให้พลาดโอกาสในการเขียนโปรแกรม
  • บน Game Boy Advance ไม่สามารถเขียนวิดีโอเมมโมรีเป็นหน่วย 8 บิตได้ และถ้าทำแบบนั้นกราฟิกจะเพี้ยน มันทำงานได้บนอีมูเลเตอร์ แต่บนฮาร์ดแวร์จริงพบปัญหาและต้องแก้ไขภายหลัง มีการพัฒนา toolchain สำหรับ GBA สำหรับภาษา Nim ด้วย
  • บางครั้งคอมไพเลอร์จะทำ optimization โดยแทนที่ฟังก์ชันคัดลอกหน่วยความจำด้วย memcpy เดิมคาดว่า optimization นี้จะเกิดขึ้นเฉพาะใน user space และคาดหวังว่าออปชัน -nostdlib จะจัดการเรื่องนี้โดยอัตโนมัติได้
  • มีการเสนอให้ใช้ bitfield เป็นวิธีใช้งาน packed structs ใน C พร้อมยกตัวอย่างโค้ด C ที่ใช้ได้จริง
  • จำเป็นต้องมีวิธีแก้ปัญหาหน่วยความจำของ Game Boy Advance สงสัยว่า LLVM รองรับความสามารถนี้หรือไม่ และคิดว่าการรวมเข้ากับ Zig ไม่น่าจะยาก