God of War در PSP، مجددا در WebAssembly کامپایل شده و در مرورگر اجرا می شود
آدرس مقاله: https://github.com/snuri00/psp-web-recomp آدرس نظرات: https://news.ycombinator.com/item?id=49991243 امتیاز: 228 # نظرات: 111
بازی های PSP در حال اجرا در مرورگر بدون شبیه ساز. کد ماشین MIPS بازی زودتر از موعد به C++ ترجمه شده، در WebAssembly کامپایل شده و در مقابل یک پیاده سازی مجدد کوچک از سیستم عامل و تراشه گرافیکی PSP که با WebGL2 طراحی می شود، پیوند داده شده است.
اولین عنوانی که به این شکل مطرح شد God of War: Chains of Olympus است. از بوت تا منوها، کات سین ها و مبارزات، با سرعت 60 فریم در ثانیه در صحنه های اندازه گیری شده تا کنون در کروم و فایرفاکس روی لپ تاپ، تا چهار برابر وضوح PSP و روی گوشی هایی با کنترل های لمسی روی صفحه نمایش پخش می شود. موسیقی، گفتار و جلوه های صوتی کار می کند. در حال حاضر فیلم ها حذف شده اند.
God of War: Ghost of Sparta نیز با همین فیلمنامه ها همراه بود. به رمزگشایی DRM PSP برای یک فایل کوچک، تعداد انگشت شماری تماس های سیستمی و رفع نور نیاز داشت، و هیچ کارایی کارایی نداشت: با سرعت 55 تا 60 فریم در ثانیه با وضوح سه برابر وضوح اصلی اجرا می شود.
هیچ داده بازی در اینجا گنجانده نشده است. شما یک تصویر دیسکی از یک بازی که مالک آن هستید می آورید و اسکریپت های موجود در این مخزن آن را به یک صفحه وب در دستگاه شما تبدیل می کند.
کامپایل مجدد. PSRecomp فایل اجرایی رمزگشایی شده را تجزیه و تحلیل میکند، توابع آن را پیدا میکند و C++ را برای آنها در واحدهای ترجمه 16 کیلوبایتی کد مهمان منتشر میکند. این کد در برابر یک فایل رجیستر و مدلی از حافظه PSP اجرا می شود. این پروژه تعداد انگشت شماری اصلاحات را به PSRecomp (در وصله های/) و یک هدف جدید برای آن، نمایه وب در پروفایل/ اضافه می کند.
یک هسته کوچک PSP. هر چیزی که بازی از سیستم عامل PSP بخواهد با شبیه سازی سطح بالا در نمایه/میزبان پاسخ داده می شود: رشته های همکاری با سمافورها، پرچم های رویداد و تماس های تلفنی، پارتیشن های حافظه، سیستم فایل (با داده های دیسکی که از طریق درخواست های محدوده HTTP پخش می شوند، بنابراین فقط فایل اجرایی از جلو دانلود می شود)، کنترلر، پیام های ذخیره شده و پخش کننده فایل های صوتی و صوتی. زمان مهمان در فریمها پیش میرود، بنابراین یک بازی 60 هرتز ثابت را میبیند هر چقدر که میزبان سریع اجرا شود.
گرافیک. جنرال الکتریک، تراشه گرافیکی PSP، به لیست های نمایش داده می شود. ge.cpp آنها را روی CPU رمزگشایی میکند، از جمله فرمتهای راس، پوستهسازی، نورپردازی، تولید بافت، برش دادن و حذف کردن صورت پشتی، و مثلثهای دستهبندی شده دستی و حالت رندر به ge_gl.cpp. در آنجا، فریمبافرها به اهداف رندر WebGL تبدیل میشوند که با مکان خود در VRAM کلید میخورند، بنابراین افکتهایی که به یک بافت رندر میشوند و دوباره آن را میخوانند، روی GPU باقی میمانند.
تفسیر مجدد فرمت پیکسل (بازیها بافرهای 32 بیتی را بهعنوان بافتهای 16 بیتی خوانده میشوند)، انتقالهای استنسیل در آلفا، مه و بلوک PSP نیز روی GPU شبیهسازی شدهاند، و همه چیز میتواند یک تا چهار برابر 480×272 اصلی ارائه شود.
دو رشته مانند PSP. در PSP تراشه گرافیکی از طریق لیست نمایش یک فریم کار می کند در حالی که CPU لیست بعدی را آماده می کند و بازی ها در اطراف آن نوشته می شوند. در اینجا جنرال الکتریک و زمینه WebGL آن روی یک رشته کاری با OffscreenCanvas اجرا میشود: صفبندی یک لیست به یکباره برمیگردد و فقط تماسهای همگام صریح منتظر میمانند. یک فریم به جای مجموع هر دو، هر رشتهای که شلوغتر است هزینه دارد.
صدا. جلوه های صوتی از پیاده سازی مجدد سینت سایزر صدای PSP (32 صدای ADPCM با پاکت های زیر و بم و ADSR)، موسیقی و گفتار از جریان های ATRAC3+ که با رمزگشای FFmpeg رمزگشایی شده اند و ترکیب به AudioWorklet می رود.
اولین ساخت قابل پخش با سرعت 6 فریم در ثانیه اجرا شد. بیشتر راه رسیدن به 60 به جای اینکه رندر سریعتر انجام شود، از این بود که بفهمیم زمان واقعا کجا رفته است.
God of War فریم بافر خود را بدون انتظار برای خالی عمودی تعویض میکند، بنابراین بدون هیچ چیزی مانع از آن میشود، بازی برای هر فریمی که به صفحه نمایش میرسد حدود هشت فریم میکشد. با نگه داشتن نخی که دو بار در یک جای خالی جابهجا میشود تا مورد بعدی، ترفندی PPSSPP نیز استفاده میکند، کار در هر فریم نمایش داده شده را به تنهایی 8 برابر کنید.
در WebAssembly، خواندن ساعت از طریق std::chrono از طریق clock_gettime و تبدیل BigInt در جاوا اسکریپت انجام می شود. تایمرهای پروفایلی که آن را به صورت اولیه میخواندند، حدود یک سوم فریم طول میکشد تا زمانی که برای خواندن performance.now() تنها زمانی که پروفایل روشن است ساخته شوند.
فایرفاکس هر بارگذاری بافر WebGL را در فرآیند GPU خود کپی می کند و پس از هر تغییری در بافر فهرست، کل بافر را در قرعه کشی بعدی مجددا تأیید می کند. بنابراین، یک حلقه فهرست مشترک 4 مگابایتی فایرفاکس را به 3 فریم در ثانیه کاهش داد. دادن به هر قرعه کشی یک بافر شاخص کوچک خودش آن را ثابت کرد. راه حل مخالف، نوشتن تکه تکه دادههای راس در یک بافر بزرگ، به هیچ مرورگری کمک نکرد و باعث توقف تلفنها شد، زیرا درایورهای GPU موبایل زمانی که بافری که ممکن است GPU هنوز در حال خواندن است، منتظر بمانند یا کپی کنند.
PSP بافر استنسیل خود را در کانال آلفای فریم بافر نگه می دارد و God of War از آن برای سایه های پیش بینی شده و محدود کردن عبور تاری استفاده می کند. انعکاس استنسیل و آلفا به یکدیگر با پاس های تمام صفحه درست بود اما 60 میلیون پیکسل اضافی در هر فریم در 4× هزینه داشت. ردیابی اینکه کدام مستطیل ها، کدام بیت های شابلون و کدام مقادیر ثابت واقعا تغییر کرده است، این رقم را به حدود 7 میلیون کاهش داد.
در نهایت، God of War لیست نمایش هر فریم را در صف قرار می دهد و قبل از اینکه منتظر بماند، روی فریم بعدی کار می کند. اجرای جنرال الکتریک روی رشته خودش، هزینه یک مبارزه شلوغ را از بازی به علاوه گرافیک، حدود 17 میلیثانیه در فایرفاکس، به بزرگتر از این دو، در حدود 10 میلیثانیه تبدیل کرد.
Ghost of Sparta بدون تغییر در اسکریپتها یا کامپایلر از یک ZIP به یک صفحه از طریق port.sh رفت و سپس برای همیشه در هنگام بوت منتظر ماند. یک فایل 176 بایتی با پرچم DRM PSP باز می کند، کلید خود را به sceIoIoctl می دهد و آنچه را که می خواند بررسی می کند. فایل به صورت PGD است، فرمت amctrl.prx با موتور کریپتو KIRK رمزگشایی میشود، و برای بازیهای دیسکی که به AES-128 میرسد با سه کلید از خزانه کلید KIRK: بررسی هدر مبتنی بر CMAC و حالت شمارنده برای دادهها. profile/host/pgd.cpp آن را پیاده سازی می کند.
مشکل بعدی آسمان سفید بود و منوها همان مه سفید را داشتند. نصف کردن نقشههای یک فریم منجر به یک لایه ابری میشود که با روشنایی روشن کشیده میشود، که کدورت آن از آلفای نور محیط جهانی ناشی میشود، عاملی که کد نورپردازی از آن حذف شده بود. کارایی نیازی به کار ندارد: هزینه یک فریم 6 تا 8 میلی ثانیه است، مانند Chains of Olympus.
شما به git، CMake، Ninja، یک کامپایلر C++20 و Python 3 نیاز دارید. همه چیز روی لینوکس اجرا شده است. macOS باید بتواند نسخه مرورگر را بسازد، اما آزمایش نشده است، و برنامه آزمایشی بومی به سربرگ های EGL و OpenGL ES (libegl-dev و libgles-dev در دبیان و اوبونتو) نیاز دارد. برای هر بازی برای دیسک استخراج شده، کد تولید شده و بیلدها، انتظار حدود 2 گیگابایت فضای دیسک را داشته باشید.
port.sh دیسک را استخراج می کند (یک ISO، یک ZIP حاوی یک یا یک پوشه از قبل استخراج شده)، PSP_GAME/SYSDIR/EBOOT.BIN را رمزگشایی می کند، آن را به C++ ترجمه می کند، مانیفست را برای پخش بقیه دیسک می نویسد و صفحه را می سازد. چند دقیقه طول می کشد؛ God of War از ZIP به صفحه قابل پخش در یک لپتاپ 8 هستهای در حدود چهار میرود. -native را اضافه کنید تا یک runner بدون هد نیز بسازید که می تواند فریم ها را روی تصاویر رها کند و صدا را ضبط کند، که سریع ترین راه برای دیدن اینکه یک بازی جدید تا چه حد می رسد.
فایل های اجرایی روی دیسک های خرده فروشی رمزگذاری شده اند. PSP_DECRYPT هر ابزاری را که به عنوان ابزار <in> <out> فراخوانی می شود نام می برد و یک ELF ساده می نویسد، مانند DecEboot یا pspdecrypt. PPSSPP همچنین میتواند یک فایل اجرایی رمزگشایی شده را هنگام اجرای بازی (تنظیمات، ابزارها، ابزارهای توسعهدهنده) حذف کند.
انتظارات خود را بر این اساس تنظیم کنید: دو بازی تا کنون مطرح شده اند، و هر دو عنوان Ready at Dawn بر روی یک موتور ساخته شده اند، بنابراین در مورد فاصله یک بازی از استودیو دیگر اطلاعات کمی دارند. یک بازی دیگر به احتمال زیاد در یک فراخوانی سیستمی متوقف میشود که هنوز هیچکس اجرا نشده است، که بهعنوان [hle] اجرا نشده ثبت شده است...، یا از ویژگی GE استفاده میکند که این رندر کار نمیکند. docs/internals.md ابزارهایی را برای یافتن موارد گم شده توصیف می کند، و کد به گونه ای سازماندهی شده است که افزودن تماس چند خط باشد.
این صفحه از SharedArrayBuffer برای رشتههای خود استفاده میکند، بنابراین باید به صورت جدا شده از مبدا متقابل، با Cross-Origin-Opener-Policy: same-origin و Cross-Origin-Embedder-Policy: require-corp ارائه شود. scripts/serve.py هر دو هدر را ارسال میکند و از درخواستهای Range که پخش دیسک به آنها متکی است، پشتیبانی میکند. برای امتحان کردن آن بر روی تلفن، یک تونل در مقابل آن قرار دهید، به عنوان مثال تونل cloudflared --url http://127.0.0.1:8613، که سرصفحه ها را از آن عبور می دهد. هر کسی که آدرس را داشته باشد میتواند بازی را در حین اجرای تونل بارگیری کند، بنابراین آن را برای خود نگه دارید و پس از پایان کار آن را متوقف کنید.
مرورگرهایی که نمیتوانند WebGL2 را روی OffscreenCanvas بکشند، بهطور خودکار به یک رشته برمیگردند. ?threads=0 آن را مجبور میکند و ?profile یک زمانبندی هر فریم را به نوار وضعیت اضافه میکند.
این مخزن فقط حاوی کد اصلی، وصله های PSRecomp و کد شخص ثالث تحت مجوز خود است. این شامل هیچ کد یا داده بازی نیست. ++C تولید شده و WebAssembly ساخته شده ترجمه های اجرایی بازی هستند، بنابراین به صاحبان بازی تعلق دارند: آنها را در دستگاه خود نگه دارید و آنها را منتشر نکنید. از تصاویر دیسک بازی هایی که دارید استفاده کنید. God of War یک علامت تجاری Sony Interactive Entertainment است. این پروژه به سونی یا هیچ ناشر بازی وابسته نیست یا توسط آن تأیید شده است.
PSRecomp توسط همکارانش (MIT) کامپایل مجدد استاتیک را انجام می دهد. PPSSPP و JPCSP بسیاری از رفتار سختافزاری را که در اینجا شبیهسازی شدهاند، مستند کردهاند، و کپی مستقل PPSSPP از رمزگشای ATRAC3/ATRAC3+ FFmpeg برای موسیقی و گفتار استفاده میشود (LGPL 2.1 یا بالاتر، در profile/third_party/at3_standalone). Emscripten WebAssembly را می سازد.
کد موجود در این مخزن تحت مجوز MIT موجود است، به LICENSE مراجعه کنید. profile/third_party/at3_standalone مجوز LGPL 2.1 خود را حفظ می کند.
متن اصلی (انگلیسی)
God of War on PSP, recompiled to WebAssembly and running in the browser
Article URL: https://github.com/snuri00/psp-web-recomp Comments URL: https://news.ycombinator.com/item?id=49991243 Points: 228 # Comments: 111