God of War trên PSP được biên dịch lại sang WebAssembly, chạy mượt trong trình duyệt

Công nghệ07 tháng 10, 2026·6 phút đọc

Dự án psp-web-recomp biên dịch trước mã máy MIPS của game PSP sang C++ rồi build thành WebAssembly, giúp God of War: Chains of Olympus và Ghost of Sparta chạy trực tiếp trên trình duyệt mà không cần trình giả lập. Game đạt 60 khung hình/giây ở độ phân giải gấp tới bốn lần bản gốc, kèm âm thanh và điều khiển cảm ứng trên điện thoại.

God of War trên PSP được biên dịch lại sang WebAssembly, chạy mượt trong trình duyệt

God of War trên PSP được biên dịch lại sang WebAssembly, chạy mượt trong trình duyệt

Một dự án mã nguồn mở mang tên psp-web-recomp đang gây chú ý trong giới lập trình khi đưa các tựa game PSP lên trình duyệt web mà không cần bất kỳ trình giả lập nào. Thay vì mô phỏng phần cứng theo cách truyền thống, dự án biên dịch trước mã máy MIPS của game sang C++, sau đó build thành WebAssembly và liên kết với một bản cài đặt lại gọn nhẹ của hệ điều hành cùng chip đồ họa PSP, hiển thị bằng WebGL2.

Bản demo game PSP chạy trong trình duyệtBản demo game PSP chạy trong trình duyệt

Tựa game đầu tiên được đưa lên theo cách này là God of War: Chains of Olympus. Game chạy trọn vẹn từ màn hình khởi động, menu, các đoạn phim cắt cảnh cho tới các pha chiến đấu, đạt 60 khung hình/giây ở độ phân giải lên tới gấp bốn lần bản gốc trên Chrome và Firefox, thậm chí chơi được trên điện thoại với bộ điều khiển cảm ứng trên màn hình. Nhạc nền, lời thoại và hiệu ứng âm thanh đều hoạt động; chỉ các đoạn phim video tạm thời bị bỏ qua.

Không phải trình giả lập, mà là biên dịch lại

Điểm khác biệt cốt lõi nằm ở cách tiếp cận. Dự án sử dụng PSPRecomp để phân tích file thực thi đã giải mã, tìm ra các hàm và sinh mã C++ tương ứng theo từng đơn vị dịch 16 KiB mã khách. Đoạn mã này chạy dựa trên một tập thanh ghi và mô hình bộ nhớ của PSP.

Bên cạnh đó là một nhân PSP thu nhỏ, trả lời mọi yêu cầu mà game gửi tới hệ điều hành thông qua kỹ thuật mô phỏng cấp cao: luồng hợp tác với semaphore, cờ sự kiện và callback, phân vùng bộ nhớ, hệ thống file, tay điều khiển, đầu ra âm thanh, cùng các hộp thoại lưu dữ liệu. Đáng chú ý, dữ liệu đĩa được truyền trực tuyến qua HTTP Range request, nên chỉ file thực thi được tải về trước.

Menu tiêu đề của game trong trình duyệtMenu tiêu đề của game trong trình duyệt

Về đồ họa, chip GE của PSP được cấp các display list, giải mã trên CPU rồi chuyển thành các tam giác và trạng thái render cho WebGL. Các framebuffer trở thành render target của WebGL, giúp những hiệu ứng render ra texture rồi đọc lại vẫn nằm trên GPU. Kiến trúc hai luồng giống PSP được giữ nguyên: chip đồ họa chạy trên một worker thread với OffscreenCanvas, nhờ đó một khung hình chỉ tốn chi phí của luồng bận hơn thay vì tổng cả hai.

Bài học từ việc tối ưu hiệu năng

Bản chơi được đầu tiên chỉ đạt 6 khung hình/giây. Phần lớn chặng đường lên 60 khung hình đến từ việc tìm hiểu thời gian thực sự bị tiêu tốn ở đâu, chứ không phải từ việc làm renderer nhanh hơn.

  • God of War hoán đổi framebuffer mà không chờ xung quét dọc, khiến game vẽ khoảng tám khung hình cho mỗi khung hình hiển thị. Giữ luồng hoán đổi hai lần trong một khoảng quét dọc — một thủ thuật mà PPSSPP cũng dùng — đã giảm khối lượng công việc xuống tám lần.
  • Việc đọc đồng hồ qua std::chrono trong WebAssembly phải đi qua clock_gettime và chuyển đổi BigInt trong JavaScript, ngốn tới một phần ba thời gian mỗi khung hình cho tới khi được sửa để chỉ đọc performance.now() khi bật profiling.
  • Firefox sao chép mọi lần tải buffer WebGL sang tiến trình GPU, nên một index ring dùng chung 4 MB khiến trình duyệt này rớt xuống còn 3 khung hình/giây. Giải pháp là cấp cho mỗi lệnh vẽ một index buffer nhỏ riêng.
  • PSP lưu stencil buffer trong kênh alpha của framebuffer. Việc soi gương stencil và alpha bằng các lượt vẽ toàn màn hình tốn thêm 60 triệu pixel mỗi khung hình ở mức 4×, nhưng chỉ theo dõi những vùng thực sự thay đổi đã kéo con số này xuống khoảng 7 triệu.

Cảnh chiến đấu trong game chạy trên trình duyệtCảnh chiến đấu trong game chạy trên trình duyệt

Tựa game thứ hai và những thách thức mới

God of War: Ghost of Sparta tiếp bước qua cùng bộ script mà không cần chỉnh sửa bộ biên dịch. Tuy nhiên, nó gặp trở ngại khi chờ mãi ở màn hình khởi động vì mở một file 176 byte có gắn cờ DRM của PSP. File này ở định dạng PGD — thứ mà amctrl.prx giải mã bằng engine mã hóa KIRK, thực chất là AES-128 với ba khóa từ kho khóa của KIRK. Sau khi bổ sung, tựa game này chạy ở 55–60 khung hình/giây tại độ phân giải gấp ba lần bản gốc, không cần tối ưu thêm.

Tự tay đưa game của bạn lên web

Dự án yêu cầu git, CMake, Ninja, trình biên dịch C++20 và Python 3, hiện đã chạy ổn trên Linux. Quy trình khá đơn giản:

PSP_DECRYPT=/path/to/decrypter scripts/port.sh mygame "My Game.iso"

Script sẽ trích xuất đĩa, giải mã file EBOOT.BIN, dịch sang C++ và build trang web. God of War mất khoảng bốn phút để đi từ file ZIP tới trang chơi được trên một laptop 8 nhân. Lưu ý rằng các file thực thi trên đĩa bán lẻ đều được mã hóa, nên người dùng cần tự cung cấp công cụ giải mã như DecEboot hoặc pspdecrypt.

Lưu ý về pháp lý và kỳ vọng

Dự án không kèm bất kỳ dữ liệu game nào. Người dùng phải tự cung cấp ảnh đĩa của game mình sở hữu, và mã C++ sinh ra cũng như WebAssembly build được đều thuộc về chủ sở hữu game — cần giữ trên máy cá nhân, không công bố. Dự án không liên kết cũng không được Sony hay bất kỳ nhà phát hành nào bảo trợ.

Đến nay mới có hai tựa game chạy được, và cả hai đều là sản phẩm của Ready at Dawn trên cùng một engine, nên chưa nói lên nhiều về việc các game từ studio khác sẽ đi được tới đâu. Nhiều khả năng một game mới sẽ dừng ở một system call chưa được cài đặt. Dù vậy, với mã nguồn mở theo giấy phép MIT và tài liệu hướng dẫn chi tiết, đây là một bước tiến thú vị cho thấy tiềm năng của kỹ thuật static recompilation trong việc hồi sinh các tựa game cũ ngay trên nền tảng web hiện đại.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗