ขณะนี้ SDL รองรับ DOS แล้ว
(github.com/libsdl-org)- มีการเพิ่ม พอร์ต DOS บนพื้นฐาน DJGPP เข้ามาใน SDL และถูกผสานเข้า main แล้วในสภาพที่ค่อนข้างครบทั้งวิดีโอ เสียง อินพุต เธรด ตัวจับเวลา ระบบไฟล์ และสายการ build
- มีการใช้งานที่ปรับให้เข้ากับสภาพแวดล้อม DOS ครอบคลุมทั้ง วิดีโอ VGA และ VESA 1.2+, การเล่นเสียงตระกูล Sound Blaster, คีย์บอร์ดและเมาส์ PS/2, จอยสติ๊กแบบ BIOS, เธรดเชิงความร่วมมือ และตัวจับเวลา PIT
- ปัญหา seek/read ของ DJGPP ถูกหลบเลี่ยงด้วยวิธี dump และกู้คืนบัฟเฟอร์เมื่อ seek ทำให้ปัญหาการอ่านผิดพลาดของ
SDL_LoadWAVและอาการหน่วงหลายวินาทีหายไป และเส้นทางเสียงก็ถูกปรับให้ลดการ re-enter ของ IRQ และอาการ stutter - หน้าจอดำในโหมด fullscreen เชื่อมโยงกับการเลือกโหมด INDEX8 และมีการปรับไปในทิศทางของการจัดลำดับโหมดอย่างมีเหตุผลแทนการเพิ่ม hint เฉพาะ DOS รวมถึงแก้ปัญหาความโปร่งใสของเคอร์เซอร์ด้วยคอมมิตเพิ่มเติม
- การทดสอบบนฮาร์ดแวร์จริงยังมีจำกัด และยังขาดบางฟีเจอร์ เช่น การบันทึกเสียง,
SDL_LoadObject, และการทำงานเฉพาะ DOS ของSDL_TIMEแต่ผ่านการตรวจสอบ 46 รายการและถูก merge โดยนับเป็นฟีเจอร์ของ 3.6.0
ขอบเขตการรองรับแพลตฟอร์ม DOS
- มีการเพิ่ม พอร์ต DOS เข้าไปใน SDL และไปถึงระดับที่ค่อนข้างสมบูรณ์บนพื้นฐาน DJGPP
- งานนี้ถูกแบ่งกันทำโดยหลายคน และในช่วงท้ายมีการเพิ่มทั้งการแก้เสถียรภาพและการเติมฟีเจอร์ที่ขาดอยู่
- มีการทดสอบ DevilutionX อย่างกว้างขวางบน DOSBox แต่ ไม่มีการทดสอบบนฮาร์ดแวร์จริง
- บางส่วนถูกตัดออกโดยตั้งใจเพราะไม่มีวิธีทดสอบที่เหมาะสม
- มีการสรุปฟีเจอร์ที่รองรับไว้อย่างชัดเจน
- วิดีโอ รองรับ framebuffer ของ VGA และ VESA 1.2+, สี RGB และ indexed color 8 บิต, การตั้งค่า palette ผ่าน VGA DAC, vsync และ hardware page flipping รวมถึงการบันทึกและกู้คืนสถานะ VBE ตอนออกจากโปรแกรม
- เสียง รองรับ Sound Blaster 16, Sound Blaster Pro และ Sound Blaster 2.0/1.x โดยใช้เส้นทาง IRQ-based DMA และ double-buffer auto-init
- อินพุต ครอบคลุมคีย์บอร์ด PS/2 พร้อม extended scancode, เมาส์ INT 33h และจอยสติ๊ก gameport บน BIOS INT 15h
- เธรด ใช้ cooperative scheduler ด้วย
setjmp/longjmpและ stack patching พร้อม fallback ทั่วไปสำหรับ mutex, semaphore, TLS และ condition variable - มีการใส่จุด yield ใน event pump และฟังก์ชัน delay เพื่อรักษา การตอบสนองของเสียงและเธรดอื่น ๆ
- ตัวจับเวลา เป็นการใช้งานแบบ PIT บน
uclock()ของ DJGPP ที่มีความละเอียดราว 1.19 MHz - ระบบไฟล์ จัดการ
GetBasePathและGetPrefPathด้วยsearchpath()ของ DJGPP และมี fallback สำหรับการทำงานไฟล์ระบบแบบ POSIX - การ build มีทั้งไฟล์ CMake cross-compilation toolchain, งาน CI สำหรับ DJGPP และ preseed cache เพื่อให้ configure ได้เร็วขึ้น
- ยังมีการระบุฟีเจอร์ที่ไม่ได้รวมไว้อย่างชัดเจน
- ไม่มี การบันทึกเสียง รองรับเฉพาะการเล่นกลับ
- ไม่มี native implementation ของ
SDL_TIMEโดยเฉพาะ แต่ใช้ Unixgettimeofdayผ่าน POSIX layer ของ DJGPP แทน - ไม่รองรับ การโหลด shared library จึงไม่มี
SDL_LoadObject
กระบวนการพัฒนาและการเปลี่ยนแปลงสำคัญ
- พอร์ต DOS ถูกเสริมความสามารถทีละขั้นผ่านหลายคอมมิต ครอบคลุม วิดีโอ เสียง อินพุต ตัวจับเวลา เธรด และสายการ build
- หลังจากงานช่วงแรก ก็มีการเติม stdio buffering, การทำงานเสียง, video subsystem, ระบบไฟล์, เมาส์, คีย์บอร์ด, CI และการตรวจจับแพลตฟอร์มตามลำดับ
- ในส่วน stdio และการเข้าถึงไฟล์ มีการหลบเลี่ยง ปัญหา seek/read เฉพาะของ DJGPP
- เดิมเคยพยายามปิดบัฟเฟอร์ของ stdio SDL_IOStreams แต่ภายหลังเปลี่ยนเป็นวิธี dump และกู้คืนบัฟเฟอร์เมื่อมีการ seek
- การเปลี่ยนแปลงนี้เร็วกว่าการปิดบัฟเฟอร์ทั้งหมดมาก และยังหลีกเลี่ยงปัญหาการอ่านค่าผิดหลัง
fseek - อาการที่
SDL_LoadWAVใช้เวลาหลายวินาทีในการอ่านtest/sample.wavหายไป และข้อมูลที่อ่านได้ก็ถูกต้อง
- วิธีจัดการเสียงก็ถูกปรับต่อเนื่องโดยเน้นเสถียรภาพ
- เริ่มจากการรองรับ Sound Blaster 16 แล้วค่อยเพิ่ม pre-SB16 8-bit mono และ SB Pro stereo
- การมิกซ์เสียงย้ายจากเดิมที่รันใน IRQ handler โดยตรง ไปผ่าน main loop แล้วภายหลังย้ายกลับไปยัง SDL audio thread
- มีการเปลี่ยนทิศทางเพื่อหลีกเลี่ยงปัญหา re-entry ภายใน IRQ และลด stutter โดยทำให้ DMA buffer ครึ่งเก่ากลายเป็น silence ระหว่างโหลด
- ยังมีการจัดระเบียบเรื่องการปรับ sample rate, การ polling สถานะ DSP, เหตุผลของการจองหน่วยความจำ DMA และการปลด IRET wrapper หลังคืนค่า interrupt vector
- ส่วนวิดีโอก็ถูกขยายรายละเอียดให้เข้ากับข้อจำกัดของ DOS
- มีการเพิ่ม implementation เบื้องต้นที่ทำงานกับ software renderer ผ่าน VESA interface
- ต่อมามีการเพิ่ม palette 8 บิต, VBE page flipping, การกู้คืนสถานะ, vsync ในโหมด single buffer และ โหมด VESA banked framebuffer
- ถ้าเป็น VBE 1.2+ ที่ไม่มี LFB จะคัดลอก framebuffer ด้วย bank switching และจะปิด page flipping ในโหมดนี้
- มีการบันทึกและกู้คืนสถานะ VBE ทั้งหมดตอนเริ่มและจบการใช้งานวิดีโอ เพื่อให้การสลับโหมดสะอาดเรียบร้อย
- อินพุตและการจัดการ interrupt ก็ถูกขัดเกลาจนใช้งานจริงได้
- คีย์บอร์ดรองรับทั้ง extended scancode และปุ่ม Pause โดยใช้ ring buffer แบบง่ายสำหรับเก็บอีเวนต์
- เมาส์ใช้ INT 33h function
0x1Bเพื่ออ่านค่าความไว - จอยสติ๊กจำกัดการ polling แกนไว้ราว 60 Hz เพื่อลดต้นทุนของ BIOS timing loop แต่ยัง polling ปุ่มโดยตรงตลอดเพื่อคงความตอบสนอง
- มีการ lock โค้ดและข้อมูลของ ISR เพื่อป้องกัน page fault ระหว่าง interrupt
- ปัญหาเรื่องการ build และการตรวจจับแพลตฟอร์มก็ได้รับการแก้ไข
- มีการเพิ่ม CI job สำหรับ DJGPP และเพิ่มการตรวจจับแพลตฟอร์ม DOS ใน CMake
- ใส่
SDL_PLATFORM_DOSไว้ในรายการยกเว้นของSDL_RunApp()เพื่อไม่ให้ชนกับ launcher เฉพาะ DOS - แม้ DJGPP จะนิยาม
__unix__แต่ DOS ไม่มี GTK หรือ display server จึงแยกSDL_Gtk_Quit()ออกจาก DOS เพื่อกัน link error - ยังรองรับกรณีที่ toolchain DJGPP บางชุดใช้คำนำหน้า
i386-pc-msdosdjgpp-gcc
สถานะการทดสอบและข้อจำกัดที่ยังเหลือ
- การทดสอบอัตโนมัติไม่ได้จบอย่างราบรื่นทั้งหมด แต่ไปถึงระดับที่ สามารถรันจบได้ด้วยแพตช์
- เพราะมีปัญหาบางส่วนกับฟังก์ชัน formatting มาตรฐาน ทำให้การทดสอบอัตโนมัติไปไม่สุด และจึงใช้แพตช์หลบเลี่ยงเพื่อให้รันทดสอบได้ครบ
- ยังมีบางเคสที่ล้มเหลวอยู่ แต่ไม่ได้รวมการแก้เพราะยังไม่มั่นใจว่าวิธีแก้ฟังก์ชัน formatting นั้นควรเป็นแบบใด
- โดยรวมแล้วเดโมส่วนใหญ่ทำงานได้ในระดับที่พอคาดหวังได้
- มีการเพิ่มผลจากการใช้งานจริงด้วย
- บน DOSBox และ DOS 6.22 บนบอร์ด Vortex86 หน้าต่างแบบไม่เต็มจอทำงานได้ดีกับทั้งโปรแกรมทดสอบและโค้ดของผู้ใช้
- แต่ fullscreen ในช่วงเวลานั้นยังให้ หน้าจอดำว่างเปล่า ในตัวอย่างอย่าง
draw.exe --fullscreen - ความเร็วอาจช้าแต่ยังถือว่าใช้งานได้
- ยังพบปัญหาในโปรแกรมทดสอบบางตัวด้วย
sprite.exeปิดตัวทันทีบน DOSBoxwm.exeและdraw.exeไม่แสดงผล แต่กด ESC แล้วออกได้testpaletteเกิด segfault
ปัญหาการเลือกความลึกสีในโหมดเต็มจอและการปรับแก้
- สาเหตุโดยตรงของหน้าจอดำใน fullscreen คือ พฤติกรรมที่
SDL_GetClosestFullscreenDisplayMode()ตกไปเลือกโหมด INDEX8- ถ้าแอปพลิเคชันไม่รองรับการเรนเดอร์แบบ INDEX8 หน้าจอก็จะกลายเป็นสีดำ
- ใน implementation ภายใน มีการจัดการให้พิจารณา INDEX8 เฉพาะเมื่อผู้ใช้ตั้งค่าโหมด fullscreen แบบ INDEX8 ไว้อยู่แล้วเท่านั้น
- ตอนแรกมีการตอบสนองด้วยการซ่อนโหมด INDEX8 หลัง
SDL_HINT_DOS_ALLOW_INDEX8_MODESเฉพาะบน DOS- จุดประสงค์คือให้แอป opt-in อย่างชัดเจน เฉพาะเมื่อจัดการได้ถูกต้องเท่านั้น
- แต่บน main branch มีการเปลี่ยนแปลงที่ เลือก bit depth สูงสุดแทนต่ำสุด อยู่ก่อนแล้ว จึงมีการตรวจสอบว่าจะแก้ปัญหาได้หรือไม่
- การเปลี่ยนแปลงนี้แก้ปัญหา bpp ได้ แต่กลับสร้างปัญหาใหม่คือคำขอ best fit แบบ 640x480 ถูกเลือกเป็น 1024x768
- สุดท้ายการเปลี่ยนแปลงนั้นถูกย้อนกลับ และการแก้ที่ดีกว่าจะไปจัดการใน PR แยกต่างหาก
- ท้ายที่สุด hint เฉพาะ DOS ถูกถอดออก และเปลี่ยนไปใช้การจัดลำดับโหมดอย่างมีเหตุผล
- มีการเพิ่มคอมมิต
Remove SDL_HINT_DOS_ALLOW_INDEX8_MODES and order modes logically - มีการสรุปว่าเมื่อ #15442 ถูก merge แล้ว แม้แอปจะไม่ได้ตั้ง palette หรือเลือกโหมด fullscreen เอง การเลือกโหมดอัตโนมัติก็จะทำงานได้ถูกต้อง
- พร้อมกันนั้นก็มีการขีดเส้นว่าจะไม่ไล่ขุดปัญหาอื่นของ SDL ทั้งหมดให้จบใน PR นี้ไม่สิ้นสุด
- มีการเพิ่มคอมมิต
การเรนเดอร์เดโมและการแก้เคอร์เซอร์
- ปัญหาที่เดโมแสดงผลเป็นสีดำไม่ได้ขึ้นอยู่กับ PR นี้เพียงอย่างเดียว แต่ขึ้นกับสถานะการ merge ของ #15442
- ตราบใดที่
SDL_GetClosestFullscreenDisplayMode()ยังชอบความลึกสีต่ำที่สุด พอร์ตนี้ก็จะเลือก INDEX8 และถ้าแอปไม่ตั้ง palette ก็จะได้หน้าจอดำ - เมื่อ merge PR ดังกล่าวเข้ามาในเครื่องท้องถิ่น ก็มีการยืนยันว่าตัวทดสอบทั้งหมดทำงานได้
- ตราบใดที่
- ปัญหาภาพที่เหลืออยู่คือ ความโปร่งใสของเคอร์เซอร์
- หลังตรวจสอบในเครื่อง พบว่าเหลือเพียงเคอร์เซอร์ที่ยังไม่โปร่งใส
- เพื่อแก้ปัญหานี้จึงมีคอมมิต
Don't convert cursor if dest is not INDEX8 - หลังแก้แล้ว แม้ในโหมด RGB จะใช้เวอร์ชันที่ยังไม่เหมาะที่สุด แต่ก็ทำงานได้ถูกต้องทั้งใน RGB และ INDEX8
- ยังอาจมีพื้นที่ให้ปรับประสิทธิภาพเพิ่มเล็กน้อยใน XRGB1555 และ RGB565 แต่ถือว่ามีลำดับความสำคัญต่ำ
การรีวิวและการตัดสินใจ merge
- มีการเห็นว่า PR นี้เหมาะกับการ squash merge
- เพราะ GitHub ยังเก็บการอ้างอิงถึง PR ไว้ในคอมมิตผลลัพธ์ ทำให้ยังติดตามกระบวนการทำงานย้อนหลังได้
- ยังมีข้อเสนอให้ใส่การให้เครดิตเพิ่มเติมในคอมมิตผลลัพธ์ด้วย
- มีข้อความตัวอย่างที่ระบุชัดให้เพิ่ม
Co-authored-byสองคนและTested-byหนึ่งคน
- ผู้รีวิวระบุว่า หลัง merge แล้วจะกลับมาเขียนถ้อยคำบางส่วนใน build script ให้สะอาดขึ้นอีก
- ก่อน merge ขั้นสุดท้าย มีการจัดทิศทางให้ merge PR ที่เกี่ยวข้องอื่น ๆ ก่อน แล้วค่อยเดินหน้า PR ของ DOS
- หลัง “Last call on DOS pull request!” ก็มีการยืนยันสถานะการ merge ของ PR ที่เกี่ยวข้อง
- จากนั้น PR นี้ก็ถูก merge เข้า main ในสถานะ 46 checks passed
- หลัง merge ก็มีการระบุขอบเขตของรีลีสไว้อย่างชัดเจน
- การเปลี่ยนแปลงนี้ถูกนับเป็นฟีเจอร์ของ 3.6.0
-
จะไม่ cherry-pick ไปยัง 3.4.x
- วันถัดจากการ merge มีการลบสาขางาน DOS ออก
งานต่อเนื่องและปัญหาฮาร์ดแวร์ที่ยังเหลือ
- ยังมีการหยิบยกปัญหาที่ implementation ของ
4f07(SetDisplayStart)บน GPU Nvidia บางรุ่นทำงานไม่ถูกต้องขึ้นมาด้วย- มีการแนบลิงก์ เธรด VOGONS พร้อมระบุว่า แม้รายงานจะบอกว่ารองรับ แต่ในทางปฏิบัติมี GPU ที่ใช้งานไม่ได้จริง
- ช่วงการทดสอบอาจกว้างตั้งแต่ GeForce 9300 ถึง 3060 แต่เป็นเพียงตามอุปกรณ์ที่มีอยู่ จึงยังไม่ใช่ขอบเขตที่ครบถ้วน
- ฝั่งโปรเจกต์ก็สังเกตเห็นปัญหาการแสดงผลแบบเดียวกันในการทดสอบ
- มีความเห็นว่าการให้ SDL ปิดฟีเจอร์ตามผู้ผลิต GPU ไม่ใช่แนวทางที่พึงประสงค์ และมีการพูดถึงความเป็นไปได้ของ hint สำหรับให้ผู้ใช้ควบคุมเอง
- มีทิศทางว่า hint ใหม่ที่ให้ผู้ใช้ควบคุม
page_flip_availableโดยตรงอาจดีกว่า - แต่ยังไม่รีบทำทันที และอาจเพิ่มในภายหลัง
- มีทิศทางว่า hint ใหม่ที่ให้ผู้ใช้ควบคุม
- หลัง merge ยังมีการระบุ hint สำหรับใช้งาน framebuffer โดยตรงด้วย
- ระบุว่าเมื่อเปิด
SDL_HINT_DOS_ALLOW_DIRECT_FRAMEBUFFERปัญหาSetDisplayStartข้างต้นอาจไม่สำคัญมากนัก
- ระบุว่าเมื่อเปิด
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ตอนนี้ถ้ามีแค่ SDL สำหรับ UEFI ก็จะสามารถรันเกมได้แม้ใน สภาพแวดล้อมก่อนบูต OS
ทั้งในแง่ว่าความปลอดภัยแน่นหนาขึ้นหรือยังคงเข้าถึงได้อยู่ https://www.zdnet.com/article/minix-intels-hidden-in-chip-operating-system/
แต่เท่าที่รู้ UEFI ไม่มี ไดรเวอร์เสียง และทุกวันนี้แม้แต่ชิปออดิโอ codec ก็ยังมีแต่ datasheet ที่ให้ภายใต้ NDA เลยเขียนเองได้ลำบาก
ที่ชวนอึ้งกว่าคือ graphics output protocol ไม่มี ข้อมูล vsync ทำให้ blitting แบบไม่เกิดภาพฉีกทำไม่ได้ ซึ่งแย่กว่า VGA เสียอีก
ลองคิดว่าเปิดเครื่องมาด้วยเมนูแบบ grub แล้วมี รายชื่อเกมคลาสสิก เรียงมาให้เลือก ก็น่าตื่นเต้นดี
สิ่งที่ทำให้ภาพหน้าจอนี้ยิ่งขำคือ DosBOX เองก็ถูกสร้างขึ้น บน SDL
อันนี้ใช้ DJGPP เลยสลับ CPU ไปเป็น โหมด 32 บิต ผ่าน DPMI
เพราะงั้นอารมณ์โอลด์สคูลแท้ ๆ แบบ segmented memory, near pointer และข้อจำกัด 64KB เต็มไปหมดจะไม่ได้สัมผัสกันนัก
เจ๋งดี
ชวนให้นึกว่าจะเป็นยังไงถ้าใช้คู่กับ MS-DOS executable สำหรับ 386+ ของ FreeBASIC ที่รองรับ SDL binding
[1] - https://github.com/freebasic/fbc
ผมตั้งใจมาหลายปีแล้วว่าอยากพอร์ต OHRRPGCE ที่มีต้นกำเนิดจาก DOS กลับไปลง DOS อีกครั้ง
และถ้านึกถึงช่วง SDL 1.2 ที่ SDL ไล่ตัดพอร์ตและการรองรับ OS ออกไปแทบหมด การที่ SDL3 ได้การรองรับ DOS กลับคืนมา ก็น่าประหลาดใจไม่น้อย
สมบูรณ์แบบ
เช้านี้ผมกำลังพัฒนาอยู่ใน Turbo C ที่อยู่ใน DOSBox-X ที่อยู่ใน Debian GNU/Linux ที่อยู่ใน VMware Fusion บน macOS พอดี ข่าวนี้ใช่เลย
ยังพอจำได้ลาง ๆ ว่าเคยทำงานด้วย turboc เมื่อหลายสิบปีก่อน
ถ้าพูดแบบเคร่ง ๆ แล้ว อันนี้ทำได้อยู่แล้วด้วย HXDOS
เพราะมัน emulation ของ DirectDraw ได้ดีพอที่ SDL จะใช้งานได้
ถ้างั้นก็สงสัยว่าคอมไพล์เป็น SDL target แบบไหน
เป็น Win32 แบบ full-screen ที่ผูกขาดเลย หรือเป็น ความละเอียด VESA อย่าง 640x480?
ในโปรเจกต์ โอเพนซอร์ส อย่าง SDL การรองรับแบบนี้จะเข้ามาได้มักขึ้นอยู่กับว่าการเปลี่ยนแปลงนั้นลุกล้ำแค่ไหน และผู้ร่วมพัฒนาจะ ดูแลรักษาต่อจริงไหม
แต่ละโปรเจกต์มีนโยบายต่างกัน และผมไม่รู้ว่านโยบายของ SDL เป็นยังไง แต่พอร์ตมีอยู่เยอะแล้ว ก็คงรู้ตัวดีว่ากำลังรับอะไรไว้
ตัวอย่างที่ผมชอบที่สุดคือ openbsd luna88k https://www.openbsd.org/luna88k.html
ผมไม่รู้เลยว่ามีผู้ใช้จริงอยู่มากแค่ไหน มันน่าจะเป็นเครื่องที่ค่อนข้างหายากและออกในญี่ปุ่นเท่านั้น และถ้ามีผู้ใช้จริง ส่วนใหญ่ก็คงอยู่ในญี่ปุ่นซึ่งอยู่นอกสายตาผม เลยให้ความรู้สึกเหมือนมีผู้ใช้แค่คนพอร์ตเพียงคนเดียว
แต่ถึงอย่างนั้น ทุกรีลีสก็ยังมี ไฟล์และแพ็กเกจสำหรับ luna88k โผล่มาเหมือนผุดออกจากป่า หลังวันออกอย่างเป็นทางการไปไม่กี่สัปดาห์
ผมเดาว่าคงใช้เวลานานเพราะต้องคอมไพล์บน luna88k จริง ๆ และไม่ว่าอย่างไร แค่นั้นก็เพียงพอแล้วที่จะทำให้มันยังคงเป็น แพลตฟอร์มฮาร์ดแวร์ทางการของ OpenBSD
ตัวผมเองไม่ได้อยากได้ luna88k หรอก แต่ก็เคารพคนที่ทำให้มันยังเดินต่อไปได้จริง ๆ
เหมือน SDL กำลังย้อนกลับไปหา รากยุค Loki อีกครั้ง
เยี่ยมเลย
ทำไมน่ะเหรอ? ไม่รู้เหมือนกัน แต่เท่ก็คือเท่
แค่ดูจาก Internet Archive ก็พอเห็นว่า ถ้ามีคีย์บอร์ดกับเมาส์ เกมระดับความซับซ้อนแบบ AAA ช่วงกลางยุค 90 ก็แทบจะรันได้ทุกที่
เกมอย่าง Tomb Raider, Command & Conquer และ Quake เป็นตัวอย่าง และถ้าคุณอยากได้ แพลตฟอร์มที่มันก็ใช้งานได้เลย มันก็น่าสนใจมาก
พอมี SDL เพิ่มเข้ามาก็ยิ่งง่ายขึ้นอีก
ดีใจมาก
อันนี้ทำให้ผมมีความสุขจริง ๆ