- Một lỗi kỳ lạ đã được phát hiện ở cảnh đầu của Half-Life 2, nơi cánh cửa không mở khiến tiến trình bị chặn lại
- Nguyên nhân là khi cửa mở, đầu mũi chân của người bảo vệ đứng bên trong va chạm với quỹ đạo của cánh cửa, khiến cửa đóng lại rồi bị khóa
- Cùng một va chạm này cũng tồn tại trong mã nguồn gốc, nhưng kết quả khác nhau do chênh lệch độ chính xác giữa phép toán dấu phẩy động x87 năm 2004 và phép toán SSE năm 2013
- Trong môi trường x87, một chuyển động xoay rất nhỏ đẩy bàn chân lệch đi nên va chạm được giải quyết, nhưng trong SSE thì lượng xoay không đủ nên cửa bị đóng lại
- Đây là một ví dụ tiêu biểu cho thấy độ chính xác dấu phẩy động và khác biệt trình biên dịch có thể ảnh hưởng đến hành vi thực tế của trò chơi như thế nào
Lỗi được phát hiện trong quá trình port Half-Life 2 sang VR
- Năm 2013, trong lúc Valve thử nghiệm port Team Fortress 2 sang VR, họ cũng khiến Half-Life 2 và Portal 1 dùng cùng engine có thể chạy được trên VR
- Portal 1 gây chóng mặt đến mức gần như không thể chơi trong VR vì hiện tượng méo góc nhìn
- Half-Life 2 thì hoạt động tương đối tốt, và cảm giác nhập vai đặc trưng của VR được tăng cường ở các phân cảnh đi thuyền, xếp thùng và chiến đấu với manhack
- Trong lúc thử nghiệm, một nhà phát triển chơi toàn bộ game bằng VR từ đầu đến cuối thì phát hiện ra trạng thái không thể tiếp tục ở cảnh ga tàu đầu game
Phân tích nguyên nhân cửa không mở
- Trong kịch bản gốc, người bảo vệ (thực ra là Barney) gõ cửa rồi nói “vào đi”, sau đó khi người chơi bước vào phòng thì trò chơi sẽ chuyển sang đoạn script tiếp theo
- Nhưng trong tình huống lỗi, cánh cửa lạch cạch rồi tự khóa và đóng hẳn lại, người bảo vệ tiếp tục chỉ vào cửa còn người chơi thì bị mắc kẹt
- Ngay cả khi build lại mã nguồn gốc của Half-Life 2 thì vấn đề tương tự vẫn xảy ra, gây ra sự bối rối như thể một lỗi sinh ra do quay ngược thời gian
Nguyên nhân gốc: thay đổi trong cách tính toán dấu phẩy động
- Vào thời điểm phát hành năm 2004, Half-Life 2 sử dụng tập lệnh toán học x87, với cấu trúc trộn lẫn độ chính xác 32, 64 và 80 bit
- Trong các bản build từ năm 2013 trở đi, tập lệnh SSE được dùng mặc định, nên độ chính xác tính toán được giới hạn rõ ràng ở 32 bit hoặc 64 bit
- Ở cả hai môi trường, cánh cửa và đầu mũi chân của người bảo vệ đều va chạm, nhưng kết quả khác nhau do chênh lệch cực nhỏ trong tính toán của engine vật lý
- Trên x87, khi va chạm xảy ra người bảo vệ xoay đi một chút xíu, khiến bàn chân rời khỏi cửa và cửa mở ra
- Trên SSE, mức xoay giảm đi rất nhỏ nên bàn chân vẫn chạm vào cửa, làm cửa đóng lại và bị khóa
Cách sửa và giải quyết
- Sau khi xác định được vấn đề, lỗi được khắc phục bằng một chỉnh sửa đơn giản: dịch vị trí của người bảo vệ lùi lại khoảng 1 mm
- Quá trình debug cũng tốn khá nhiều thời gian, bao gồm cả việc phải học lại cách dùng các công cụ cũ
- Trường hợp này cho thấy khác biệt về độ chính xác và thay đổi trong thiết lập trình biên dịch có thể làm thay đổi cách mã cũ vận hành
Phản ứng từ cộng đồng
- Các nhà phát triển đồng cảm với nhận xét rằng “vấn đề lúc nào cũng là do độ chính xác dấu phẩy động”
- Một số người nhắc đến trường hợp thay đổi tính toán va chạm trong các bản remake của Sonic 1, 2 và 3 để chỉ ra điểm tương đồng
- Cùng với bài học rằng “mã thì giống nhau nhưng trình biên dịch thì khác”, đây được xem là một ví dụ gợi nhắc về sự khó khăn trong việc duy trì mã legacy
- Những nhà phát triển khác cũng liên hệ điều này với lý do vì sao trong Fallout 4 và các game khác, NPC được thiết kế để không đi xuyên qua cửa
- Nhìn chung, nhiều người xem đây là một trong những câu chuyện lỗi thú vị nhất
1 bình luận
Bình luận trên Hacker News
Hồi trước khi còn làm phát triển game, tôi nhớ đã gặp lỗi assertion fail do tính toán FPU chỉ xảy ra trên một số PC nhất định
Nguyên nhân là phần mềm nhập liệu bằng bút đã inject DLL vào mọi tiến trình và reset chế độ FPU về mặc định
Cuối cùng, chúng tôi chuyển phần mã cấu hình FPU từ giai đoạn khởi tạo sang vòng lặp sự kiện để tránh ảnh hưởng từ DLL bên thứ ba
Một trong những mục tiêu của tôi là khiến Valve dùng Nix
Tôi nghĩ điều này sẽ còn hấp dẫn hơn khi hỗ trợ Windows đang được triển khai
Như vậy không chỉ mã nguồn gốc mà cả toolchain và dependencies của thời điểm đó cũng có thể được tái tạo hoàn toàn, nên có lẽ sẽ dễ lần ra nguyên nhân gốc của những lỗi kiểu này hơn nhiều
Làm tôi nhớ đến meme “DOOR STUCK”
Video liên quan
Tôi tự hỏi liệu “Half-Life 2 VR beta” có thật sự chơi được không
Nếu có thì tại sao tôi lại không biết, còn nếu không thì tại sao đến giờ vẫn chưa có
Tôi cũng rất muốn thử Portal VR. Mọi người bảo nó gây say nặng, nhưng tôi miễn nhiễm với say VR nên rất đáng để thử
Mức độ hoàn thiện cao đến mức khiến tôi chơi lại HL2 sau một thời gian dài
Khi chuyển từ x87 sang SSE, một số phép tính bị hỏng là chuyện khá thường gặp
TF2 cũng từng gặp như vậy: ở bản build Linux, game dùng SSE nên cách tính đạn dược hơi khác một chút
Hộp nhỏ cho +40 hoặc +41, và điều đó khác nhau tùy theo OS của server
Mỗi lần vào server mới, khá vui khi đoán xem nó đang chạy OS nào
Chỉ đổi từ x87 sang SSE thôi mà game đã hỏng, nên thật kỳ lạ khi chuyển đổi x86→ARM lại hoạt động tốt đến vậy
Nó dùng thanh ghi 80-bit nên có độ chính xác cao hơn, nhưng lại có hành vi lạ như mất độ chính xác khi spill ra bộ nhớ
Trước đây khi debug một software synthesizer, tôi cũng từng gặp lỗi độ chính xác tương tự
Mô phỏng mạch RC cần trạng thái đổi khi tiến gần về 0, nhưng trên một số CPU nhất định thì giá trị denormal không bị flush nên điều kiện không bao giờ thỏa mãn
Cuối cùng tôi chỉnh ngưỡng đại khái thành 0.7 và 0.01 thì mọi thứ hoạt động tốt trên mọi nền tảng
Nói ngoài lề một chút, tôi định làm một bản sao Twitter với tính năng ban ngay nếu ai đó đăng blog theo kiểu nhiều đoạn văn