2 पॉइंट द्वारा GN⁺ 2024-06-09 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • PS2 के VU floating-point multiplication में 1-बिट की arithmetic error होती है, इसलिए कुछ खास मानों पर 1 * X, X से अलग हो सकता है
  • VU developer manual के अनुसार X * 1 की सटीकता की गारंटी है, लेकिन 1 * X के लिए वही गारंटी नहीं है, और यही फर्क emulator detection का संकेत बनता है
  • उदाहरण में brute force से खोजे गए समस्या पैदा करने वाले मानों में से 129.5f का उपयोग करके असली PS2 और emulator के व्यवहार का अंतर दिखाया गया है
  • implementation में VU0 macro mode में 129.5f और 1 को multiply करने के बाद सिर्फ यह तुलना की जाती है कि result मूल input से अलग है या नहीं
  • PCSX2, Play!, DobieStation, hps2x64 फिलहाल इस व्यवहार को emulate नहीं करते, और detection की कठिनाई 1/5 आंकी गई है

PS2 VU multiplication में होने वाली 1-बिट error

  • यह तरीका PS2 emulator detection series की दूसरी प्रविष्टि है, और इसे VU1, VU0 micro mode, VU0 macro mode में इस्तेमाल किया जा सकता है
  • उदाहरण implementation को सरल रखने के लिए VU0 macro mode का उपयोग करता है
    • इसमें VU0 को coprocessor की तरह इस्तेमाल किया जाता है, इसलिए इसे EE CPU से सीधे चलाया जा सकता है
    • अलग VU program संभालने की जरूरत नहीं पड़ती
  • VU developer manual में MUL, MULi जैसे multiplication instructions पर 1-बिट arithmetic error की टिप्पणी है
    • 1 * X मूल मान X से अलग हो सकता है
    • अगर VF[fs] को multiplicand के रूप में इस्तेमाल किया जाए, तो X * 1 रूप के result की सटीकता की गारंटी होती है
  • बिट क्यों खोता है, यह ठीक-ठीक स्पष्ट नहीं है

detection value और implementation तरीका

  • इस error को detect करने के लिए ऐसा नंबर चाहिए जो समस्या पैदा करे, और उसे खोजने का सबसे आसान तरीका brute force है
  • लेखक ने पहले 0.5 के अंतराल पर समस्या पैदा करने वाले पहले 250 नंबरों की सूची बनाई थी, और उसे gist में प्रकाशित किया है
  • example code detection target number के रूप में 129.5f का उपयोग करता है
    • QMTC2 से VF1 में 129.5f सेट किया जाता है
    • VADDw से VF2 में 1 बनाया जाता है
    • VMUL से VF1 = 1 * 129.5f की गणना की जाती है
    • QMFC2 से result को EE side पर लाकर input से तुलना की जाती है
  • return value in[0] != out[0] है, और अगर मूल मान और multiplication result अलग हों, तो माना जाता है कि VU multiplication error मौजूद है

emulator के अनुसार प्रभाव

  • फिलहाल PCSX2, Play!, DobieStation, hps2x64 इस PS2 VU multiplication behavior को emulate नहीं करते
  • क्योंकि सिर्फ एक नंबर को 1 से multiply करके result देखना होता है, इस detection तरीके की कठिनाई 1/5 स्तर की मानी गई है

1 टिप्पणियां

 
GN⁺ 2024-06-09
Hacker News की राय
  • पुराने ARM emulation का पता लगाने की सबसे सरल तरकीबों में से एक, जो शायद Game Boy Advance copy protection में भी इस्तेमाल हुई थी: PC+4 लोकेशन, यानी ठीक अगली instruction में एक trap instruction स्टोर करना
    असली ARM में pipeline की वजह से, जब PC पर execute हो रहा होता है और PC+4 decode हो रहा होता है, तब PC+8 पढ़ा जाता है, इसलिए नई स्टोर की गई instruction का असर नहीं होना चाहिए। अगर emulator hardware pipeline को emulate नहीं करता, तो वह उस instruction को execute कर देगा
    2004 की कई emulation-रोधी तकनीकों के साथ इस पर ज़्यादा विस्तार से समझाने वाला लेख: https://mgba.io//2014/12/28/classic-nes/
    • Texas Instruments TI320C40 digital signal processor में pipeline की समस्या और भी अजीब थी: उसमें branch delay slot (https://en.wikipedia.org/wiki/Delay_slot) था, जहाँ branch के बाद की एक या उससे ज़्यादा instructions असल branch से पहले execute होती थीं, और load delay slot भी था, जहाँ register में स्टोर की गई value कुछ instructions बाद ही दिखाई देती थी
      शायद कुछ cycles तक register value undefined रहती थी। ऐसे chip के लिए बहुत कसकर optimized assembly code लिखना किसी खास तौर पर खराब स्वाद वाले Zachtronics clone खेलने जैसा लगता था, इसलिए काफ़ी भयानक अनुभव था
    • x86 में भी prefetch queue ने इसी तरह का व्यवहार बनाया था, लेकिन Intel ने Pentium के बाद के CPU में self-modifying code को detect करना शुरू कर दिया, जिससे अगर आप जल्द execute होने वाली instruction को modify करें तो उसका हमेशा असर होता है
      काफ़ी बाद में किसी ने एक और ऐसा edge case ढूँढा जो detect नहीं होता था: एक self-overwriting repeated string instruction
      https://silviocesare.wordpress.com/2009/02/02/anti-debugging...
    • कुछ pipeline CPU self-modifying code के साथ compatibility बनाए रखते हैं, इसलिए अगर pipeline में चढ़ी हुई instruction को overwrite किया जाए, तो वे इसे detect करके pipeline खाली कर देते हैं
      x86 में ऐसा mechanism है, लेकिन 64-bit variant में इसे आख़िरकार हटा दिया गया या नहीं, यह पक्का नहीं है
    • क्या यही वजह थी कि VisualBoyAdvance में Dragon Ball Z: The Legacy of Goku II ROM कभी-कभी काम नहीं करता था?
  • यही वजह है कि 100% accuracy वाले emulation को इंडस्ट्री में कारीगरी का क्षेत्र माना जाता है
    आपको original hardware और software के हर अजीब व्यवहार को जानना ही नहीं, बल्कि उसे कितना भी विचित्र क्यों न हो, वैसा ही reproduce भी करना पड़ता है। अपने-आप में यह मुश्किल है, और ऊपर से performance impact का भी ध्यान रखना पड़ता है
    • emulators को accuracy के बारे में व्यावहारिक होना पड़ता है। ज़्यादा आधुनिक systems को emulate करते समय 100% hardware accuracy और इस्तेमाल लायक performance, दोनों को एक साथ लक्ष्य बनाना आम तौर पर असंभव होता है, इसलिए ऐसे समझौते स्वीकार करने पड़ते हैं जो तकनीकी रूप से असली hardware से अलग हों, लेकिन व्यवहार में लगभग कोई दिखने वाला फ़र्क न पैदा करें
      JIT recompiler का इस्तेमाल करने का मतलब है कि आप original hardware के साथ पूरी तरह cycle-by-cycle accurate नहीं हो सकते, लेकिन जब तक game code जानबूझकर emulator को तोड़ने के लिए न बनाया गया हो, यह आम तौर पर समस्या नहीं बनता
      Dolphin को भी यह संतुलन संभालना पड़ा था, जब कुछ commercial Wii games ने असली Wii CPU के cache behavior की बारीकियों का फायदा उठाने वाला anti-emulator code डाल दिया था। सिद्धांततः वे असली CPU cache को emulate करके games को smoothly चला सकते थे, लेकिन performance overhead शायद 10 गुना slowdown जैसा होता, जिससे खेलना संभव नहीं रहता, इसलिए उन्होंने workaround patch चुना
      https://dolphin-emu.org/blog/2017/02/01/dolphin-progress-rep...
  • emulation में शुरुआत कैसे की जाती है? यह software के भीतर भी बेहद मुश्किल niche field जैसी लगती है
    ऐसा लगता है जैसे आपको electronics और गहरे programming magic, दोनों की समझ चाहिए
    • बाकी चीज़ों की तरह धीरे-धीरे शुरुआत की जा सकती है
      शुरुआत में, और ज़्यादातर मामलों में अंत तक भी, आपको गहरे magic को समझने की ज़रूरत नहीं होती। आम तौर पर आप spec पढ़ते हैं और उसी के मुताबिक implement करते हैं। code structure को बिखरने से बचाने की क्षमता चाहिए, लेकिन इसके common patterns होते हैं, और एक-दो emulator बना लेने के बाद यह काफ़ी आसान हो जाता है
      electronics समझने की ज़रूरत भी लगभग कभी नहीं पड़ती। आप सिर्फ behavior को emulate कर रहे होते हैं। अगर original hardware behavior में कोई bug मिलता है, तो आम तौर पर emulator में special handling डालना काफ़ी होता है। ऐसा behavior क्यों आता है, यह समझने में electronics ज्ञान मदद कर सकता है, लेकिन वह व्यावहारिक से ज़्यादा ऐतिहासिक रुचि की चीज़ है
      इसमें कुछ अनोखी कठिनाइयाँ ज़रूर हैं। जब समस्या आती है, तो आप आम तौर पर hardware की समझ, emulator implementation, और जिस game को emulate किया जा रहा है, इन तीनों को एक साथ debug कर रहे होते हैं। सही कारण को सीमित करना मुश्किल हो सकता है। फिर भी, पहले बस कुछ बनाकर देखने की सलाह दूँगा। यह साफ-सुथरा नहीं होगा, लेकिन हर emulator लोकप्रिय games को किसी तरह चलाने के लिए special cases से भरा होता है। अगर कुछ गंदे hacks से game चल जाता है, तो वही कर लेना चाहिए। original hardware behavior को बिल्कुल सही implement करना ज़रूरी नहीं, game को चलाना ज़रूरी है
    • hardware documentation पढ़ने से शुरुआत की जा सकती है, और मशीन को electronic circuit level पर समझने की ज़रूरत नहीं है। यह digital circuit simulation नहीं है, इसलिए इसे इतना जटिल होने की ज़रूरत नहीं
      8-bit CPU कुछ bytes की state, यानी सिर्फ registers वाला एक simple state machine होता है। यह program को एक-एक byte पढ़ता है, और CPU उस byte को पढ़ने के बाद जो करेगा, आपको बस उसका अनुकरण करना होता है। ये बहुत सरल operations होते हैं, जैसे संख्याएँ जोड़ना-घटाना, या bytes पढ़ना और स्टोर करना
      http://www.6502.org/users/obelisk/6502/registers.html
      http://www.6502.org/users/obelisk/6502/instructions.html
      6502 CPU emulator program के अगले कुछ bytes पढ़ता है, उन bytes को instructions की तरह interpret करता है, और instructions को execute करता है। इस प्रक्रिया में वह CPU के कुछ registers या counters को update करता है, arithmetic या bit operations करता है, और ज़रूरत पड़ने पर एक जगह से दूसरी जगह 1 byte data पढ़ता या स्टोर करता है। फिर इस प्रक्रिया को एक infinite loop में दोहराता है

यह fetch-decode-execute cycle का simulation है
https://en.wikipedia.org/wiki/Instruction_cycle

  • "emulation" से क्या मतलब लिया जा रहा है, इस पर निर्भर करता है
    बहुत पहले SID music files चलाने के लिए मैंने 6502 interpreter को UNIX से Classic Macintosh पर port किया था। जब तक वह पर्याप्त तेज़ चलता था, clock cycle accuracy महत्वपूर्ण नहीं थी
    यह interpreter से C code को call करने के तरीके से काम करता था
  • बहुत समय पहले जब मैंने इसमें प्रवेश करने की कोशिश की थी, तब सलाह यह थी कि बहुत simple और अच्छी तरह documented चीज़ से शुरू करो और वहीं से skill बढ़ाओ
    अभी भी इसे करना चाहता हूँ, लेकिन समय नहीं है
  • थोड़ी self-promotion करूँ तो, पिछले FOSDEM में मैंने इसी विषय पर एक talk दी थी: https://fosdem.org/2024/schedule/event/fosdem-2024-2146-how-...
    इसके अलावा, @xcv123 की sibling comment बिल्कुल सही बात कहती है
  • software emulation में यह शायद एक दिलचस्प उदाहरण है, लेकिन संभवतः इतना महत्वपूर्ण नहीं कि उस पर ध्यान दिया जाए। उस bug तक को emulate करने पर यह काफ़ी धीमा हो जाएगा
    अगर कभी FPGA से PS2 को recreate करना संभव हो गया, तो यह पता लगाना कि यह व्यवहार कैसे हुआ, किसी के लिए एक मज़ेदार project हो सकता है
    • FPGA implementations भी अक्सर software emulation projects के code या documentation के आधार पर बनाई जाती हैं
      सिर्फ़ इसलिए कि यह PS2 का FPGA version है, इसकी कोई गारंटी नहीं कि वही या मिलते-जुलते bugs implement नहीं होंगे
    • यह इस पर निर्भर करता है कि वह bug game को तोड़ता है या नहीं
    • इस bug को ठीक करना कई अन्य floating-point bugs, खासकर rounding और clamping समस्याओं को ठीक करने के काम का हिस्सा होगा
      software floating-point धीमा होगा, लेकिन सामान्य समाधान शायद PS4 के PS2 emulator का अनुसरण करेगा। यानी, हर game के लिए code के उन हिस्सों को whitelist करना जहाँ software floating-point path की अनुमति दी जाए
    • कोई अपेक्षाकृत महंगे FPGA पर पुराना और ख़राब MIPS CPU emulate क्यों करना चाहेगा? पुराने console को emulate करने का मूल उद्देश्य यह है कि hardware से स्वतंत्र होकर computer या phone पर पुराने games खेले जा सकें
  • क्या title देखकर कोई और भी यह सोचकर भ्रमित हुआ कि mouse या keyboard को गणित क्यों करनी पड़ रही है?
    यह समझने में मुझे बहुत ज़्यादा समय लग गया कि यह mouse और keyboard को जोड़ने वाले Personal System/2 port की नहीं, बल्कि PlayStation 2 की बात है
    • एक PS2 है, और दूसरा PS/2
    • जिन्होंने downvote किया: जो बात आपको स्पष्ट लगती है, वह सबको स्पष्ट हो यह ज़रूरी नहीं
      तीन-अक्षर वाले acronyms context ढूँढना वाकई मुश्किल बना सकते हैं। क्योंकि अगर सिर्फ़ acronym को Google में डालो, तो काफ़ी बार ज़्यादातर नतीजे लगभग असंबंधित निकलते हैं