2 điểm bởi GN⁺ 2024-06-09 | 1 bình luận | Chia sẻ qua WhatsApp
  • Phép nhân số thực dấu phẩy động VU của PS2 có sai số tính toán 1 bit, nên với một số giá trị nhất định, 1 * X có thể khác X
  • Theo tài liệu hướng dẫn dành cho nhà phát triển VU, X * 1 được đảm bảo chính xác, nhưng 1 * X không có bảo đảm tương tự; khác biệt này trở thành tín hiệu phát hiện trình giả lập
  • Ví dụ dùng 129.5f, một trong các giá trị gây lỗi được tìm bằng brute force, để kiểm tra sự khác biệt hành vi giữa PS2 thật và trình giả lập
  • Cách triển khai có cấu trúc đơn giản: trong chế độ macro VU0, nhân 129.5f với 1, rồi chỉ so sánh xem đầu vào ban đầu và kết quả có khác nhau hay không
  • PCSX2, Play!, DobieStation, hps2x64 hiện chưa mô phỏng hành vi này, và độ khó phát hiện được đánh giá là 1/5

Sai số 1 bit phát sinh trong phép nhân VU của PS2

  • Phương pháp này là mục thứ hai trong loạt bài phát hiện trình giả lập PS2, và có thể dùng trong VU1, chế độ micro VU0, cũng như chế độ macro VU0
  • Ví dụ sử dụng chế độ macro VU0 để đơn giản hóa triển khai
    • Vì dùng VU0 như một coprocessor, có thể chạy trực tiếp từ EE CPU
    • Không cần xử lý một chương trình VU riêng
  • Trong tài liệu hướng dẫn dành cho nhà phát triển VU, các lệnh nhân như MUL, MULi có chú thích rằng chúng có sai số tính toán 1 bit
    • 1 * X có thể khác giá trị gốc X
    • Nếu dùng VF[fs] làm số bị nhân, độ chính xác của kết quả dạng X * 1 được đảm bảo
  • Chưa xác nhận chính xác vì sao bit bị mất

Giá trị phát hiện và cách triển khai

  • Để phát hiện sai số này, cần một con số gây ra vấn đề; cách tìm kiếm dễ nhất là brute force
  • Tác giả trước đây đã lập danh sách 250 số đầu tiên gây vấn đề theo bước 0.5, và công khai danh sách đó trên gist
  • Mã ví dụ dùng 129.5f làm con số mục tiêu để phát hiện
    • Dùng QMTC2 để đặt 129.5f vào VF1
    • Dùng VADDw để tạo 1 trong VF2
    • Dùng VMUL để tính VF1 = 1 * 129.5f
    • Dùng QMFC2 để đưa kết quả về phía EE và so sánh với đầu vào
  • Giá trị trả về là in[0] != out[0]; nếu giá trị gốc và kết quả phép nhân khác nhau thì coi như có tồn tại sai số phép nhân VU

Ảnh hưởng theo từng trình giả lập

  • Hiện tại PCSX2, Play!, DobieStation, hps2x64 chưa mô phỏng hành vi phép nhân VU này của PS2
  • Vì chỉ cần nhân một con số với 1 rồi kiểm tra kết quả, độ khó của phương pháp phát hiện này ở mức 1/5

1 bình luận

 
GN⁺ 2024-06-09
Ý kiến trên Hacker News
  • Một mẹo đơn giản nhất để phát hiện giả lập ARM đời cũ, hình như cũng từng được dùng trong cơ chế chống sao chép của Game Boy Advance: lưu một lệnh bẫy ở vị trí PC+4, tức là ngay lệnh kế tiếp
    ARM thật do có pipeline nên trong lúc thực thi ở PC và giải mã ở PC+4 thì sẽ đọc PC+8, vì vậy lệnh vừa ghi mới không được ảnh hưởng. Nếu là trình giả lập không mô phỏng pipeline phần cứng thì nó sẽ thực thi lệnh đó
    Bài viết giải thích chi tiết hơn cùng nhiều kỹ thuật phá giả lập từ năm 2004: https://mgba.io//2014/12/28/classic-nes/
    • Bộ xử lý tín hiệu số Texas Instruments TI320C40 còn có vấn đề pipeline kỳ quặc hơn: nó có branch delay slot, nơi một hoặc nhiều lệnh sau nhánh sẽ được thực thi trước khi nhánh thật sự xảy ra (https://en.wikipedia.org/wiki/Delay_slot), và cũng có load delay slot, nơi giá trị ghi vào thanh ghi chỉ xuất hiện sau vài lệnh
      Có lẽ giá trị thanh ghi không được xác định trong vài chu kỳ. Viết mã assembly tối ưu sát nút cho kiểu chip này khá kinh khủng, như đang chơi một bản clone Zachtronics có gu tệ bất thường
    • Trên x86, prefetch queue cũng tạo ra hành vi tương tự, nhưng Intel sớm quyết định để CPU từ Pentium trở đi phát hiện mã tự sửa, khiến việc sửa các lệnh sắp được thực thi luôn có hiệu lực
      Mãi về sau có người tìm ra một trường hợp biên khác không bị phát hiện, đó là lệnh chuỗi lặp tự ghi đè chính nó
      https://silviocesare.wordpress.com/2009/02/02/anti-debugging...
    • Một số CPU pipeline vẫn giữ tương thích với mã tự sửa, nên nếu ghi đè lên lệnh đang nằm trong pipeline thì chúng sẽ phát hiện và xả pipeline
      x86 có cơ chế như vậy, nhưng không rõ cuối cùng nó có bị loại bỏ trong biến thể 64-bit hay không
    • Có phải đây là lý do khiến ROM Dragon Ball Z: The Legacy of Goku II đôi khi không chạy trên VisualBoyAdvance?
  • Đây chính là lý do việc theo đuổi giả lập với độ chính xác 100% thuộc về địa hạt của tay nghề thủ công bậc thầy trong ngành
    Không chỉ phải biết mọi hành vi kỳ lạ của phần cứng và phần mềm gốc, mà còn phải tái hiện nguyên trạng dù chúng có quái dị đến đâu. Chỉ riêng việc đó đã khó, chưa kể còn phải tính đến tác động hiệu năng
    • Trình giả lập cần thực tế về độ chính xác. Khi giả lập các hệ thống hiện đại hơn, việc cùng lúc nhắm tới độ chính xác phần cứng 100% và hiệu năng dùng được thường là bất khả thi, nên người ta chấp nhận những thỏa hiệp tuy khác về mặt kỹ thuật so với phần cứng thật nhưng trên thực tế gần như không tạo ra khác biệt quan sát được
      Dùng JIT recompiler thì không thể hoàn toàn chính xác đến từng chu kỳ như phần cứng gốc, nhưng trừ khi mã game cố tình được viết để phá trình giả lập thì nhìn chung không thành vấn đề
      Dolphin cũng từng phải xử lý sự cân bằng này khi một số game Wii thương mại chèn mã chống giả lập khai thác chi tiết hành vi bộ đệm của CPU Wii thật. Về lý thuyết, họ có thể giả lập cache của CPU thật để chạy game mượt mà, nhưng chi phí hiệu năng có lẽ sẽ khiến tốc độ chậm hơn khoảng 10 lần và không thể chơi nổi, nên họ chọn vá để né qua
      https://dolphin-emu.org/blog/2017/02/01/dolphin-progress-rep...
  • Người ta bắt đầu học về giả lập như thế nào? Trông nó như một ngách cực khó ngay cả trong phần mềm
    Có vẻ gần như phải hiểu cả điện tử học lẫn ma thuật lập trình ở mức sâu
    • Cũng như mọi thứ khác, hãy bắt đầu từng bước một
      Khi mới bắt đầu, và thật ra phần lớn thời gian ngay cả lúc hoàn thành, bạn không cần hiểu thứ ma thuật sâu xa nào cả. Thường chỉ cần đọc đặc tả rồi triển khai đúng theo đó. Tất nhiên vẫn cần khả năng tổ chức cấu trúc mã để nó không thành mớ hỗn độn, nhưng đã có các mẫu phổ biến và sau khi làm một hai trình giả lập thì mọi thứ sẽ dễ hơn nhiều
      Cũng hiếm khi cần phải hiểu điện tử học. Thứ được giả lập chỉ là hành vi. Khi phát hiện lỗi trong hành vi của phần cứng gốc, thường chỉ cần thêm xử lý đặc biệt vào trình giả lập. Kiến thức điện tử có thể giúp hiểu vì sao hành vi đó xuất hiện, nhưng điều đó gần với hứng thú lịch sử hơn là giá trị thực dụng
      Dĩ nhiên vẫn có khó khăn riêng. Khi có vấn đề, bạn thường phải debug đồng thời ba thứ: hiểu biết về phần cứng, phần cài đặt của trình giả lập, và chính trò chơi đang được giả lập. Việc khoanh vùng nguyên nhân chính xác có thể rất khó. Dù vậy, cứ thử làm đại một bản trước đã. Không đẹp đẽ gì đâu, nhưng mọi trình giả lập đều đầy những xử lý đặc biệt để bằng cách nào đó làm cho game phổ biến chạy được. Nếu vài cú hack lộn xộn là đủ để game chạy, thì cứ làm vậy. Không nhất thiết phải cài đặt chính xác hành vi phần cứng gốc, miễn là làm cho game chạy được
    • Có thể bắt đầu bằng việc đọc tài liệu phần cứng, và không cần hiểu cỗ máy ở mức mạch điện tử. Đây không phải mô phỏng mạch số nên không cần phức tạp đến vậy
      CPU 8-bit là một cỗ máy trạng thái đơn giản chỉ có vài byte trạng thái, tức các thanh ghi. Nó đọc chương trình từng byte một, rồi bạn chỉ cần bắt chước CPU sẽ làm gì sau khi đọc byte đó. Đó là các phép toán rất đơn giản như cộng trừ số, hoặc đọc và lưu byte
      http://www.6502.org/users/obelisk/6502/registers.html
      http://www.6502.org/users/obelisk/6502/instructions.html
      Trình giả lập CPU 6502 sẽ đọc vài byte tiếp theo của chương trình, diễn giải các byte đó thành lệnh, rồi thực thi lệnh. Trong quá trình này, nó cập nhật một vài thanh ghi hoặc bộ đếm của CPU, thực hiện phép toán số học hoặc bit, và nếu cần thì đọc hoặc lưu 1 byte dữ liệu từ vị trí này sang vị trí khác. Quy trình này được lặp lại trong một vòng lặp vô hạn

Đây là mô phỏng của chu kỳ lấy lệnh–giải mã–thực thi
https://en.wikipedia.org/wiki/Instruction_cycle

  • Còn tùy bạn định nghĩa từ mô phỏng là gì
    Trước đây tôi từng port một trình thông dịch 6502 từ UNIX sang Classic Macintosh để phát các tệp nhạc SID. Chỉ cần nó chạy đủ nhanh là được, nên độ chính xác theo chu kỳ xung nhịp không quan trọng
    Nó hoạt động bằng cách gọi mã C từ trong trình thông dịch
  • Hồi lâu lắm rồi khi tôi định bắt đầu tìm hiểu, lời khuyên là hãy bắt đầu từ thứ thật đơn giản và có tài liệu tốt, rồi nâng dần kỹ năng từ đó
    Tôi vẫn muốn thử, nhưng không có thời gian
  • Tiện quảng bá một chút, tôi đã có bài nói chuyện về chủ đề này tại FOSDEM kỳ trước: https://fosdem.org/2024/schedule/event/fosdem-2024-2146-how-...
    Ngoài ra thì bình luận anh em của @xcv123 nói rất đúng
  • Đây có lẽ là một ví dụ thú vị nhưng trong mô phỏng phần mềm thì không đáng để bận tâm lắm. Nếu mô phỏng cả lỗi đó nữa thì sẽ khá chậm
    Nếu một ngày nào đó việc tái tạo PS2 bằng FPGA trở nên khả thi, thì việc tìm ra cơ chế hành vi này xảy ra như thế nào sẽ là một dự án thú vị với ai đó
    • Nhiều bản triển khai FPGA cũng thường được xây dựng dựa trên mã hoặc tài liệu của các dự án mô phỏng phần mềm
      Không có gì đảm bảo rằng phiên bản PS2 trên FPGA sẽ không tái hiện lỗi giống hoặc tương tự
    • Còn tùy lỗi đó có làm hỏng trò chơi hay không
    • Việc sửa lỗi này sẽ là một phần của công việc sửa nhiều lỗi số thực dấu phẩy động khác, cụ thể hơn là các vấn đề về làm tròn và kẹp giá trị
      Số thực dấu phẩy động bằng phần mềm sẽ chậm, nhưng lời giải chung có lẽ sẽ theo trình giả lập PS2 của PS4: đưa vào danh sách trắng các đoạn mã cho phép dùng đường xử lý số thực dấu phẩy động bằng phần mềm theo từng trò chơi
    • Tại sao lại muốn mô phỏng một CPU MIPS cũ kỹ, tệ hại trên một FPGA tương đối đắt tiền? Cốt lõi của việc mô phỏng các máy console cũ là giúp bạn chơi game xưa trên máy tính hay điện thoại, độc lập với phần cứng
  • Có ai khác nhìn tiêu đề rồi lại bối rối không hiểu vì sao chuột hay bàn phím phải làm toán không?
    Tôi mất quá lâu mới nhận ra đây là nói về PlayStation 2 chứ không phải cổng Personal System/2 dùng để kết nối chuột và bàn phím
    • Một cái là PS2, còn cái kia là PS/2
    • Với những người đã downvote: cái gì rõ ràng với bạn không có nghĩa là rõ ràng với tất cả mọi người
      Các từ viết tắt ba chữ cái thật sự có thể khiến việc suy ra ngữ cảnh trở nên rất khó. Chỉ cần nhập riêng từ viết tắt đó lên Google thì khá thường xuyên phần lớn kết quả hiện ra lại gần như không liên quan