Як Dolphin Emulator переміг останню нескорену гру GameCube



В Dolphin 5.0 можна було хоча б завантажити будь-яку гру з GameCube. Крім однієї. Складний спосіб використання блоку управління пам'яттю в PowerPC Star Wars: The Clone Wars до недавнього часу не дозволяв грати в неї через Dolphin. Але у версії Dolphin 5.0-540 ця проблема нарешті вирішена: емулятор навчився завантажувати всі ігри GameCube з офіційною бібліотеки консолі.


Star Wars: The Clone Wars запущена в Dolphin

Чому ж Star Wars: The Clone Wars стала такою особливою? Щоб по-справжньому розібратися, в чому тут справа, вам потрібно трохи дізнатися про те, як процесор PowerPC виконує управління пам'яттю як цей процес емулюється в Dolphin.

Емуляція блоку управління пам'яттю
Блок управління пам'яттю (Memory Management Unit, MMU) відповідає за надання ігор швидкого доступу до даних і коду. Замість прямого доступу до наявної ОПЕРАТИВНОЇ пам'яті гри звертаються до віртуальної пам'яті, яка потім транслюється з допомогою MMU у фізичну пам'ять. Цей процес може виконуватися двома способами: трансляцією адрес блоків (Block Address Translations, BAT) у разі великих блоків пам'яті або таблицями сторінок в разі відображення невеликих обсягів.

Ігри отримують доступ до віртуальної, а не реальної пам'яті з кількох причин. По-перше, це дає процесору можливість кешування операцій доступу, значно підвищуючи ефективність доступу до часто використовуваних значень. По-друге, GameCube має всього 24МБ (і кілька спеціалізованих областей) ОЗП в адресному просторі з 4ГБ; це означає, що більшість адрес пам'яті не має відповідної їм ОЗУ! Якщо гра спробує отримати доступ до адреси реальної пам'яті, який не має насправді фізичної пам'яті, вона отримає в якості даних «сміття» або просто викличе збій! Завдяки використанню віртуальної пам'яті MMU може згенерувати виняток, даючи грі можливість обробити цю ситуацію або надати розробникам важливий зворотний зв'язок з корисною інформацією говорити про помилку.

Dolphin може емулювати MMU з певним ступенем точності на підставі теорій про те, як повинна вести себе гра.


MMU — це частина процесора GameCube. Фотографія з Wikimedia

Теорія 1: виконує запис тільки в дійсну пам'ять
Якщо ігри можуть виконувати запис тільки в дійсну пам'ять, то у Dolphin з цим не виникає ніяких складностей. Більшість ігор використовує стандартне BAT-відображення GameCube/Wii, і поки вони не намагаються отримати доступ до пам'яті за його межами, все, що потрібно зробити — забезпечити операції доступу в потрібні місця.



Стандартне відображення має одну трансляцію адрес блоків (BAT), транслирующую всю фізичну пам'ять. Оскільки BAT швидше, ніж таблиці сторінок, більшість ігор використовує тільки їх.

Підхід Dolphin полягає в жорсткому кодуванні цієї трансляції адреси блоку (BAT) з віртуальної пам'яті та транслюванні адреси у фізичну пам'ять. Простіше кажучи, гра запитує одну адресу в пам'яті, але консоль (а значить і Dolphin) передає їй інший з реальної пам'яті.

Існують також інші важливі відображаються частини, які не розглядаються в цій статті. Один з найважливіших — це відображений в пам'яті введення-виведення (Memory-Mapped Input/Output, MMIO), з допомогою якого процесор взаємодіє з різними пристроями (дисковим приводом, картами пам'яті тощо). Також потрібно згадати спеціальний завантажувальний сектор, але оскільки ігри не можуть отримувати до нього доступ, поки про нього говорити особливо нема чого.

Режим MMU Off в емуляторі — це настільки обрізаний функціонал MMU, щоб тільки дозволяти емуляції MMU забезпечувати завантаження ігор. Він просто надає грі область пам'яті для роботи і передбачає, що гра не буде порушувати правил. Дивно, але більшість ігор для GameCube і майже всі ігри Wii дійсно працюють з пам'яттю правильно.

Для більшості ігор GameCube, що порушують правила, повинна була знадобитися повна емуляція MMU, але хитромудрим розробникам емулятора вдалося обдурити ці ігри без зниження продуктивності з допомогою MMU Speedhack.

Теорія 2: використання неприпустимою пам'яті іграми можна передбачити
MMU Speedhack можна назвати «MMU Off+», тому що він все ще не виконує серйозної емуляції MMU. Він відображає більше ОПЕРАТИВНОЇ пам'яті, ніж має GameCube, щоб змусити гри думати, що все працює, не піклуючись про те, що ж ігри роблять насправді.



Оскільки ігри використовують ці адреси як розширене ОЗУ, просте відображення їх як дійсної пам'яті працює! Але ви напевно не розумієте, чому ж ці ігри взагалі намагаються отримати доступ до недійсною пам'яті, правда?

Все тому, що Nintendo створила бібліотеку, що дозволяє іграм скористатися 16 МБ додаткового ОЗП GameCube в якості розширеного ОЗП. Так як це додаткове ОЗП пов'язано з цифровим сигнальним процесором (DSP), воно частіше використовується в якості аудиопамяти, але технічно її можна використовувати майже для всього. Процесор не може безпосередньо відобразити додаткове ОЗП в просторі адрес через відсутність апаратної функції, тому грі доводиться виконувати читання та запис за адресою недійсною пам'яті, щоб викликати обробник виключень. Цей обробник виключень використовує прямий доступ до пам'яті (Direct Memory Access, DMA), щоб перемістити дані з додаткового ОЗП виділений грою кеш фізичної пам'яті. Потім він дає команду таблиці сторінок повідомляти, що адреса раніше недійсною пам'яті тепер вказує на місце розташування цього кеша, що дозволяє грі працювати без «вильотів»!

Якимось чином хак емулятора Dolphin примудряється працювати майже для всіх ігор, що використовують додаткове ОЗУ в якості розширеної пам'яті. Незважаючи на свою кривизну, цей хак на диво ефективний і швидко працює.

Теорія 3: доступ до недійсною пам'яті непередбачуваний
MMU Speedhack має високу продуктивність, але він працює тільки в іграх, алгоритми використання пам'яті яких типові і настільки часто зустрічаються, що були інтегровані в Dolphin. Таке жорстко заданий поведінка дозволяє емулятор Dolphin припускати, звідки гра буде виконувати зчитування і не піклуватися про те, щоб гарантувати дійсність пам'яті, до якої здійснюється доступ. Ігри з MMU Speedhack настільки стандартизовані, що підпорядковуються дуже простим правилам, але ці правила мають обмеження.

Частина ігор застосовувала власні обробника виключень і використовувала адреси пам'яті нестандартним способом, порушуючи роботу MMU Speedhack. У цих випадках Dolphin повинен перевіряти та забезпечувати дійсність адреси пам'яті, а вже потім передавати інструкції або дані емульований процесор; це виходить набагато повільніше, ніж просто вважати всі адреси дійсними.

До спроб Fiora та інших розробників оптимізувати JIT і емуляцію MMU, режим MMU Enabled був смертельним вироком для процесу гри.




Відома 21 гра, яка вимагає для роботи більше, ніж просто MMU Speedhack.

Обробка перевірок пам'яті (memcheck) повільніше, тому що вона заважає оптимізації продуктивності fastmem. Fastmem відображає простір адрес GameCube/Wii в пам'яті комп'ютера, а потім позначає для комп'ютера всю эмулируемую недійсну пам'ять як виділену. Це емулятор дозволяє використовувати Dolphin обробник виключень процесора комп'ютера для виконання «брудної роботи» при перехопленні винятків. Коли він перехоплює виняток, емулятор для обробки адреси доводиться перейти від fastmem (швидкої) до slowmem (повільної пам'яті), що може стати дуже великою проблемою для продуктивності.



Перевірки пам'яті — це базова функція MMU Enabled, і це основна причина того, що ігри з включеним MMU так повільно працювали в Dolphin. Деякі ситуації вимагали повернення до інтерпретатору, який не працює з fastmem; при цьому доступ до пам'яті був навіть повільніше, ніж звичайний доступ на консолі!

Незважаючи на часту неможливість використання, завжди варто намагатися застосовувати fastmem практично для будь-якого доступу; область завантаження fastmem зберігає всього дві інструкції, а той же доступ з допомогою slowmem може займати до 1000 інструкцій! Оскільки ми не знаємо, чи знаходиться курсор у дійсній пам'яті чи ні, ми просто завжди намагаємося застосувати fastmem з-за величезної різниці в продуктивності, яку вона дає, якщо спрацьовує.

Як сказано вище, насправді slowmem стала трохи швидше, що дозволило використовувати її на практиці. В основному це відбулося завдяки переміщенню перевірок пам'яті в кеш коду Fiora's Far Code Cache. Завдяки оптимізації обробки перевірок пам'яті і постійній готовності всіх інструкцій і даних в іграх з MMU значно зросла продуктивність. Найбільший ефект помітний Rogue Squadron 3, швидкість якого підскочила з жалюгідних 4 до майже 45 кадрів в секунду!

Зазвичай кеш Far Code Cache разом з іншими оптимизациями JIT у середньому наводив майже до двократного зростання продуктивності у всіх іграх, що вимагають MMU Enabled, з приємним винятком у вигляді Rogue Squadron 3. Саме завдяки цьому сьогодні користувачі потужних комп'ютерів можуть хоча б спробувати пограти в ігри з включеним MMU.

Теорія 3.5: Factor 5 — гади
Звичайно ж, більшість користувачів навіть не знало, наскільки гальмував Star Wars Rogue Squadron 3 до реалізації Far Code Cache, тому що він просто не завантажувався. Принаймні, так було з версією NTSC. Версія PAL кое-як завантажувалася, і саме з неї бралися характеристики швидкості до появи Far Code Cache.


Навіть якщо вам вдавалося запустити гру, нічого не зламавши, справи раптово могли стати погані, якщо важливий шматок даних зберігався на декількох сторінках.

Rebel Strike стала передостанньою завантаженої NTSC-грою з однієї причини — в ній був противний дрібний трюк з MMU, який відсунув емуляцію більше ніж на десятиліття. Rogue Squadron 3 міг зберігати дані на декількох сторінках! При тривалому читанні або запису Rebel Strike міг викликати виключення, буквально перемикаючий в процесі з дійсного на недійсний адресу! Раніше Dolphin помилково встановлював виняток на початок читання, а повинен був встановлювати його там, де насправді виняток.

Було б гарно, якщо б останньою грою з GameCube, завантаженої в Dolphin, стала гра Factor 5 (від перекладача: розробники Star Wars Rogue Squadron III: Rebel Strike), але залишалася ще одна. І на цей раз справа полягала не в дрібній помилку.

Теорія 4: гра визначає власну дійсну пам'ять
Тепер ми нарешті переходимо до Star Wars: The Clone Wars. Після всієї роботи, зробленої розробниками Dolphin для якомога ефективнішої обробки BAT і таблиць сторінок, ця гра вирішила викинути у вікно одне з найбільш базових припущень Dolphin: статичні BAT.

Dolphin робить?
Dolphin був абсолютно не готовий до ситуації, в якій буде потрібна справжня емуляція BAT. Будь-які налаштування ви ні використовували, завдяки жорстко певних допущеннях все закінчувалося дуже кисло.

MMU Speedhack/MMU Off — в цьому поєднанні справи йшли з рук геть погано. Так як Dolphin насправді не емулює MMU, він починав роботу і вирішував передати процесору будь сміття, розташований в 0x00000000. Гра закономірно «випадали», тому що це надзвичайно дурну поведінку.

MMU Enabled — якщо ви використовуєте версію, випущену до цієї статті, то в режимі MMU Enabled процес просувається трохи далі. Dolphin вдається емулювати виключення і завантажувати обробник помилок, але емулятор просто не здатний обробити те, що відбувається далі. Clone Wars користується відключенням BAT під час обробки виключень, щоб отримати більший контроль над управлінням пам'яттю. Потім вона повідомляє, що стандартні BAT і таблиці сторінок недостатньо гарні і намагається створити власні. Dolphin жорстко задає BAT. Вони не змінні. Тому коли обробник помилок повертає управління грі… вона, звичайно ж, «падає». Але, принаймні, сам Dolphin продовжує працювати, так що ви можете закрити гру і пограти в щось інше.

Ви можете задати питання: «чому б просто не створити спеціальні жорстко задані BAT для цієї гри?». Але насправді так не вийде. Гра безліч разів змінює BAT під час місій і в многопользовательском режимі; це означає, що потрібно правильна емуляція BAT.

Dolphin повинен робити
Правильна емуляція BAT передбачає, що Dolphin повинен мати можливість включення і відключення BAT на підставі дій гри, а не на припущеннях про те, чого їй хочеться. При цьому виникає проблема: ефективна емуляція MMU в Dolphin базується на тому, що він знає, де буде знаходитися дійсна віртуальна пам'ять, і руйнування цього фундаменту повністю розвалює Dolphin.

Star Wars: The Clone Wars — це єдина відома гра, яка користується чотирма короткими BAT інструкцій та BAT даних для створення власного відображення пам'яті. Для емулювання цієї гри код емуляції MMU в Dolphin має бути повністю переписаний. При цьому все дуже ускладнюється: fastmem, перевірки пам'яті, і те, що між ними.

На відміну від власних обробників винятків інших ігор, що працюють з MMU Enabled, обробник виключень The Clone Wars насправді реструктурує пам'ять. Він відключає від адресного простору стандартну BAT і під час гри багато разів створює свою власну. На попередніх зображеннях ви бачили, що BAT ставали все більш складними, роблячи емуляцію більш повною, але The Clone Wars викидає всю цю роботу на смітник!



В цей раз Dolphin не може робити ніяких припущень. Тільки повна переробка ядра емуляції BAT Dolphin здатна впоратися з цим найгіршим сценарієм. Dynamic BATs (динамічні BAT) — це повна емуляція BAT, яка дозволяє зробити те, чого просять ігри, і відображати інформацію правильно. «Завдяки» цьому переписування величезного обсягу коду від більшої частини жорстко заданих припущень емуляції MMU Dolphin довелося позбутися.

Flipping the Page Table
(від перекладача: в заголовку автори обіграють мем Flipping the Table, ні про яке «переворот» таблиці сторінок мови не йде)

Розробники Dolphin вже кілька років знали, що необхідно для завантаження Star Wars: The Clone Wars. В далекі часи (в еру версії 3.0) існувала гілка, яка могла завантажувати The Clone Wars за допомогою використання інтерпретатора. Це було невиправдано повільно і впливало на продуктивність ігор, які не використовують MMU; в ту еру продуктивність була дуже болючим питанням.

Більше року поточна реалізація (Dynamic BATs) навіть «висіла» в якості pull request, і на той момент вже могла завантажувати The Clone Wars. Вона чекала свого часу так довго, що нею навіть зайнявся інший розробник!

Причина, за якої реалізація цієї функції посіла таке довгий час, полягає в тому, що її неможливо було реалізувати, не зруйнувавши роботу всього іншого. Враховуючи все це, реалізація розробника magumagu була виконана блискуче.



Як ви бачите, дуже велику увагу приділяли тому, щоб зберегти швидкість Dolphin незважаючи на величезний обсяг переписаного коду MMU. В іграх, які не використовують MMU Enabled і використовують MMU Speedhack, продуктивність повинна знизитися менш ніж на 1%. Це велика різниця з початковими планами, в яких для ігор, що використовують MMU Enabled, падіння повинно було скласти більше 30% навіть з відключеною емуляцією MMU!

Одна з важливих особливостей реалізації Dynamic BATs в тому, що вона все одно працює з fastmem, незважаючи на очевидне ускладнення можливості переміщення дійсної пам'яті! З іншого боку, поки ігри з MMU поки працюють трохи повільніше. Падіння на 8%-15% — це значно, але ми зможемо позбутися від нього за допомогою подальших оптимізацій. Ми порахували, що величезне підвищення точності варто деякої втрати продуктивності.

Побічні ефекти переписування коду жорстко заданих BAT
Більш точна емуляція MMU призвела до того, що часте дивна поведінка ігор тепер емулюється набагато краще. Звичайно, Dynamic BATs дійсно необхідні для роботи тільки однієї гри, але інші ігри також отримали переваги більш швидкого доступу для перевірок пам'яті.

Користувачі обожнюють, коли ігри «вивалюються», правда ж? Існує досить багато ігор для Wii, які призводять до збоїв на консолі, коли гравець виконує непередбачені дії. Іноді виконання цих дій приводить навіть до аварійного завершення Dolphin! Спрощений доступ до перевірок пам'яті означає, що Dolphin може точно емулювати добре відомі глитчи в іграх, не приводячи до аварій Dolphin! Проблеми, від яких страждають Super Mario Galaxy або Twilight Princess тепер можуть бути земульовані і викликати ті ж помилки, що і на консолі, не впливаючи на продуктивність!


«Баг» з дорожнім покажчиком у Twilight Princess

Повторюся, більшості гравців не подобається, коли в іграх відбуваються збої. З цієї точки зору, Rayman Raving Rabbids TV Party (Rabbids Party Collection) більше не «вивалюються» при завантаженні міні-ігор. Можливо, так вийшло з-за невеликих змін в управлінні кешем, або, що більш імовірно, в жорстко заданих BAT/таблицях сторінок були «баги». Збій, який ніхто не міг усунути, просто зник після переписування коду — це стало приємним сюрпризом.

Поліпшення загальної емуляції процесора також нез'ясовно дозволило працювати ще двох ігор. We Love Golf!, створена розробниками Mario Golf, «вилітала» при спробі завантаження рівня. Summer Athletics 2009 просто не завантажувалася і видавала на екран якусь налагоджувальну інформацію. На ці ігри не вплинула реалізація Dynamic BATs; незрозумілим чином виправила поведінка обох ігор сама очищення коду в процесі злиття гілок. Згідно інформації, відомої про проблеми цих ігор, найімовірніше справа була в помилках кешу інструкцій і даних.

Ще одним приємним сюрпризом стало поліпшення роботи купи ромхаков Dolphin. Ромхаки Wiimm's Mario Kart Wii More Fun правильно (ну, майже) завантажують екран вибору трас!

Дуже-дуже велика удача, що все це взагалі працює. Хак не очищає icache; замість цього в управлінні звільненням і скиданням icache він покладається на процесор PowerPC, тому вважалося, що його неможливо емулювати в Dolphin без значного зниження продуктивності. Але тепер Dolphin очищає icache при зміні BAT. На жаль, між трасами гравці повинні повертатися в основне меню. Якщо ви хочете, щоб це було виправлено… то не соромтеся повідомити про це нам. Але врахуйте, що при цьому Dolphin доведеться емулювати емуляцію кешу інструкцій і даних, що в цілому підвищить вимоги до ресурсів для емуляції процесора в 14 разів! Для хардкорних або прагнуть до точності емуляції геймерів все це потрібно емулювати, але всім іншим насправді не потрібна повна і точна емуляція кеша.

Якщо ромхакеры все-таки захочуть, щоб їх гри працювали Dolphin, то ми, на жаль, маємо попросити їх не покладатися на обробку icache/dcache процесором PowerPC. Наприклад творці Project M перед фінальним релізом виправили використання icache/dcache, так що він повинен правильно працювати в Dolphin. Але якщо ви не хочете, щоб користувачі Dolphin запускали ваші ромхаки, то ви знаєте, як від цього захиститися (принаймні, поки).

висновок
Після переписування коду Dolphin зробив ще один великий стрибок в точності движка: виправлено кілька випадкових збоїв (хоча більшість гравців і не помітить різниці). Це перемога, хоча і з гіркуватим присмаком: ми змусили запускатися останню гру з GameCube, але все ще залишилося безліч нерозкритих таємниць. Звичайно, деякі ігри все ще «вивалюються», є багато проблем, які потрібно вирішити, але повністю неробочих ігор вже не залишилося.

На даний момент емуляція MMU в Dolphin здатна забезпечувати обробку будь-якої відомої гри. Єдиними, хто може це змінити, можуть стати Factor 5, але вони начебто не робили жодної гри для Wii…


Star Wars: Rogue Leaders на Wii

Однак з'ясувалося, що на Wii ще одна гра Rogue Squadron. Вона розроблена Factor 5, тому повинна експлуатувати консоль так, як ніяка гра до неї цього не робила. Але проблема в тому, що гра не була випущена, тому ми не можемо відкрити її в Dolphin. Хоча вона все-таки існує; може бути, хтось зможе спробувати запустити її в Dolphin. Може бути, хоча б подивиться на «виліт», який вона неминуче викличе. А може бути, вона навіть запуститься, і вийде зробити хоча б один скріншот? (Ну будь ласка!)

Ну да ладно. Принаймні, у нас є канал Netflix, розроблений основними членами Factor 5 вже в новій компанії. І, як ви напевно вже могли здогадатися, він не запускається в Dolphin.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.