4 điểm bởi GN⁺ 2026-01-13 | 1 bình luận | Chia sẻ qua WhatsApp
  • Đây là một trò chơi Snake chạy trên Windows, Linux và trình duyệt chỉ bằng một tệp đơn kích thước 13KiB, hỗ trợ cả ba nền tảng từ cùng một mã nguồn
  • Trò chơi tuân theo luật Snake cổ điển: điều khiển rắn ăn mồi và tránh đâm vào tường, có kèm điểm số, cấp độ và cấu trúc mê cung
  • Mỗi nền tảng được triển khai bằng C (WinAPI/X11)JavaScript (HTML5 Canvas), mỗi bản đều được nén và gộp xuống mức khoảng 3~5KiB
  • Windows chạy bằng header PE bất thường và cơ chế apphelp, Linux dùng nén lzma và shell dropper, còn trình duyệt tận dụng các mẹo HTML/CSS để thực thi
  • Kết quả ghép ba phần triển khai là một tệp thực thi đơn 13.312 byte, cho thấy tiềm năng thử nghiệm của cấu trúc tệp thực thi đa nền tảng

Thử nghiệm đa nền tảng lấy cảm hứng từ Cosmopolitan libc

  • Cosmopolitan libc là bộ công cụ có thể biên dịch mã nguồn C thành một binary đơn chạy được trên nhiều hệ điều hành
    • Hỗ trợ chạy native trên nhiều OS như Windows, Linux, BSD
  • Do không hỗ trợ GUI và bị giới hạn bởi kích thước binary lớn, tác giả chọn thử thách tự làm một trò chơi video dưới 16KiB
    • Mục tiêu là tạo một trò chơi dựa trên một mã nguồn duy nhất, chạy được trên Windows, Linux và trình duyệt

Cấu trúc và luật chơi

  • Trò chơi là Snake tiêu chuẩn, điều khiển bằng phím mũi tên hoặc WASD
    • ESC để thoát, R để đặt lại, P để tạm dừng, phím cách để bắt đầu
  • Mỗi lần ăn mồi, điểm số sẽ tăng: mồi thường được 10 điểm, mồi màu vàng (xác suất 15%) được 20 điểm
    • Mồi sẽ biến mất sau một khoảng thời gian nhất định; thời gian này được quyết định theo tốc độ của rắn, vốn tỉ lệ với chiều dài của nó
  • Ăn 10 mồi sẽ sang cấp tiếp theo, bố cục tường được thay đổi ngẫu nhiên
    • Mê cung được tạo sao cho luôn tồn tại đường đi tới mồi
    • Vị trí khởi đầu của rắn cũng là ngẫu nhiên, nhưng được đặt theo hướng có ít nhất 5 ô trống
  • Kích thước tệp game hoàn chỉnh là 13.772 byte

Cách triển khai trên từng nền tảng

  • Phiên bản Windows được viết bằng mã C dựa trên WinAPI, bao gồm script nén và stub giải nén
    • Tận dụng các byte có thể điều khiển tự do sau chữ ký MZ của header PE để nhúng shell script
    • Nhờ vậy, tệp này vừa là file thực thi Windows vừa đồng thời hợp lệ như một shell script trên Linux
    • Ở lần chạy đầu tiên có thể xuất hiện lỗi “The application was unable to start correctly (0xc0000005)”, nhưng chạy lại sẽ hoạt động bình thường
  • Phiên bản Linux dùng nén lzma, với một shell dropper nhỏ để giải nén và chạy binary ELF64 đã nén
    • Được cấu hình để chạy trong khi bỏ qua một số phần đầu và cuối của tệp
  • Phiên bản HTML tận dụng đặc tính trình duyệt bỏ qua phần đầu không cần thiết của tệp và vẫn xử lý HTML
    • CSS được dùng để che phần dữ liệu không cần thiết khỏi màn hình

Ghép thành một tệp duy nhất và cấu trúc của nó

  • Các tệp cho ba nền tảng được nối (concatenate) theo một thứ tự nhất định, để mỗi môi trường chỉ thực thi phần phù hợp với mình
    • Windows nhận diện section PE, Linux nhận diện section ELF, trình duyệt nhận diện section HTML
  • Kích thước tệp cuối cùng là 13.312 byte, tạo thành một binary polyglot chạy được ở cả ba môi trường
  • Bên trong tệp lần lượt chứa header PE của Windows, mã nén LZMA cho Linux, và mã HTML/CSS/JavaScript
    • Trong khối mã ví dụ có thể thấy lần lượt chữ ký MZ, marker ks, thẻ <html>, khối <script>...

Ý nghĩa kỹ thuật

  • Hiện thực hóa cấu trúc thực thi hỗ trợ đồng thời Windows, Linux và trình duyệt chỉ bằng một tệp duy nhất
  • Phân nhánh đường chạy theo từng nền tảng thông qua việc lồng ghép các định dạng PE, ELF và HTML
  • Một thành tựu thử nghiệm kết hợp nén, hack định dạng và thực thi đa nền tảng trong kích thước cực nhỏ chỉ 13KiB

1 bình luận

 
GN⁺ 2026-01-13
Ý kiến Hacker News
  • Tôi đã trích xuất file thực thi Linux và khá ngạc nhiên khi readelfobjdump không đọc được đúng cách
    Tìm hiểu thêm thì hóa ra nó nhét cưỡng ép tên trình liên kết động vào các trường không dùng trong PT_DYNAMIC header để tiết kiệm dung lượng

    1. Tôi tò mò không biết đây là làm thủ công hay có công cụ nào xử lý theo kiểu này
    2. Tôi cũng muốn biết có công cụ nào có thể phân tích những binary bất thường như thế này không
    • Có thể đọc bằng ndisasm hoặc trình soạn thảo hex
      Nhưng tôi nghĩ việc cố tình làm hỏng định dạng như thế này là một kiểu tiết kiệm vô nghĩa
      Nó cũng có thể xung đột với các tính năng bảo mật như antivirus hay DEP, nên tôi không muốn đụng vào những file thực thi kiểu này
    • Tôi không hiểu “choke” ở đây nghĩa là gì, trong môi trường của tôi thì cả hai công cụ đều hoạt động bình thường
  • Tôi ngạc nhiên vì kích thước file của game Zelda gốc nhỏ đến vậy
    Thật kỳ diệu khi chỉ với chừng đó code và dữ liệu mà họ tạo ra được cảm xúc và độ nhập vai lớn đến thế
    The Legend of Zelda (Wikipedia)

    • Đúng là như ma thuật vậy. Game Eindeloos trên Commodore 64 cũng chứa một bản đồ khổng lồ trong 64KB
      40 năm sau người ta mới trích xuất bản đồ ra, chỉ riêng PNG đã hơn 800KB
      Xem bản đồ game
    • Zelda 1 có dung lượng 128KB và cũng không có nén. Phần tiếp theo lớn cỡ gấp đôi
    • Các dungeon và hang động thực ra đều nằm trong cùng một bản đồ hình chữ nhật
      Các nhà thiết kế đã sắp xếp chúng như một câu đố trong giới hạn không gian
      Tham khảo cấu trúc bản đồ Zelda
  • Kết quả thử nghiệm của tôi

    • Trình duyệt: đổi phần mở rộng sang .html là chạy được
    • Linux: báo lỗi thiếu lệnh lzma, cài gói xz vào thì chạy được
    • Windows: chạy bằng .com hoặc .exe thì gặp lỗi (0xc0000005), nhưng sau khi tắt cài đặt DEP thì chạy được
    • Trên Windows 11 cũng hoạt động bình thường
    • Nếu chỉ chmod +x snake.com rồi chạy thì Mono sẽ thử mở và thất bại
      Thay vào đó, chạy bằng bash snake.com thì hoạt động tốt. Tôi dùng Debian 13
  • Điều thú vị là file này thực chất là ba file thực thi được gộp làm một
    Vì vậy về lý thuyết bạn cũng có thể nhét vào các chương trình hoàn toàn khác nhau cho từng nền tảng

  • Nó làm tôi nhớ tới game FPS 96KB tên kkrieger
    Chất lượng đồ họa của nó hồi đó thực sự đáng kinh ngạc
    kkrieger (archive)

    • Thảo luận liên quan: 2017, 2023, 2024
    • Đến giờ nó vẫn chạy được trên PC hiện đại. Tôi đã tự tải về và thử chạy
    • Gần đây khi chơi Metroid Prime 4, tôi đã nghĩ sẽ thế nào nếu làm game hiện đại theo ý tưởng này
  • Tôi muốn biết trên Mac có cách nào chạy ngoài trình duyệt không
    Tôi gặp lỗi cannot execute binary file

  • Tôi tò mò liệu có thể phát triển cơ chế này thành một universal binary thực sự hay không
    Ví dụ viết code bằng Haxe rồi biên dịch sang C++ để tạo bản Win32 và Linux,
    sau đó chuyển sang JavaScript để chạy được dưới dạng HTML,
    rồi ghép cả ba kết quả thành một file duy nhất

  • Tôi thích ý tưởng ứng dụng thực thi đơn có thể chạy ở mọi nơi chỉ với một file
    Tôi cũng đang nghiên cứu hướng này khi xây dựng một nền tảng serverless
    Chỉ với một file .html duy nhất có thể tạo ứng dụng hướng dữ liệu, với web-components được nạp từ xa
    Khả năng mở trực tiếp HTML bằng giao thức file:// rất mạnh, nhưng thường bị xem nhẹ

    • Tác giả bài gốc thực ra đã triển khai nó ba lần — bản C dùng WinAPI, bản C dùng X11, và bản JS dựa trên HTML5 Canvas
      Tức là không chỉ đơn giản mở một phiên bản trình duyệt, mà đúng hơn là đã tạo ra hai ứng dụng native hoàn chỉnh
    • Đáng tiếc là trong môi trường không có HTTPS thì trình duyệt bị hạn chế khá nhiều tính năng
    • Tôi muốn biết thêm về cách phát triển ứng dụng HTML đơn như vậy. Không rõ có ví dụ công khai nào không
  • Thật lạ khi polyglot file lại xuất hiện muộn như thế này
    Về mặt kỹ thuật thì có vẻ như 10–20 năm trước cũng đã làm được rồi

    • Tôi tò mò file polyglot đầu tiên xuất hiện từ khi nào
      EICAR.COM hiện lên trong đầu như một ví dụ rất sớm của file vừa là văn bản vừa là file thực thi
  • Nó khiến tôi nhớ tới các cuộc thi webgame siêu nhỏ như js13kGames