Приветствую вас, дорогие пикабушники!
Момент, когда мне захотелось переиграть в то что я играл на NES, доиграть в то, во что не доиграл на Sega Mega Drive, и поиграть в то, во что никогда не играл (а очень хотелось) на SNES, я точно не помню. Обстоятельства, при которых это произошло - тоже. Возможно, в числе прочего, свою роль сыграли несколько постов из этого сообщества). Но помню свои первые ощущения, когда начал играть в несовские Contra и Silk Worm на эмуляторах. Если коротко, то это были разочарования и досада. Я не смог поймать те кайф, кураж и увлеченность, которые я точно помню испытывал в девяностые, когда играл в практически любую игру на Денди. Теперь же я чувствовал себя как корова на льду.
Конечно, можно было списать это на возраст и деградацию скила, но признаваться себе в том, что я настолько старый и настолько растыка, мне не хотелось. И я начал задаваться вопросом "А, может быть, дело в чем-то еще?". Стал общаться с людьми, которые имели опыт игры и на эмуляторах и на оригинальном железе, гуглить, читать. Через некоторое время я узнал про инпут лаг. Некоторые люди описывали свои ощущения от игры на эмуляторах как "неправильная физика".
Шли годы, смеркалось. Я поднабравшись знаний и опыта, научился где, чего и как в ретроарче "подкрутить", чтобы играть было более-менее сносно. "Неправильная физика" стала более правильной. Не торт конечно, но за неимением лучшего пойдет. Далее, бороздя просторы пикабу, я наткнулся вот на этот пост. Сам пост вполне себе интересный, довольно грамотный и уж точно имеет право на существование. Но самая мякотка была в комментах. Там люди, услышав краем уха про "богоподобную" и относительно новую фишку ретроарча "Run-Ahead", абсолютно на серьёзных щах утверждали, что теперь, дескать, ретроарч имеет "более низкий инпут лаг, чем оригинальные консоли". И новодельные коллекционные консоли типа NE Mini, SNES Mini, SMD Mini - тоже отстой, потому что там внутри эмулятор, но не ретроарч и опции "Run-Ahead" там нету. Короче, нет бога, кроме RetroAch и Rasberry Pi - пророк его. А остальное от лукавого и маст дай. При этом никаких вменяемых аргументов эти люди привести не могли, с результатами тестов ознакамливаться не желали, а уж проводить тесты самим - так это уже вообще "чур меня, чур". И тут меня, что называется, накрыло.
Адекватных результатов тестирования инпут лага эмуляторов в рунете я не нашел, поэтому решил провести тесты самостоятельно. Когда работа уже была в самом разгаре, я наткнулся на пост чувака с reddit, который провел сравнительное тестирование инпут лага NES Mini и ретроарча. Причем последний тестировался как с включенной опцией "Run-Ahead", так и без нее. Но меня уже было не остановить))).
Почему меня не устроили результаты тестов, которые я нашел в рунете
С самого начала, когда я ознакомился с теми тестами инпут лага, которые уже были в рунете, я знатно охренел от небрежности методологии их проведения. За точку отсчета при замере инпут лага брался момент нажатия пальца на кнопку геймпада, который определялся визуально. Здесь, наверное, стоит пояснить чуть подробнее. Визуально мы может отследить момент, когда палец касается кнопки. Визуально мы можем отследить, когда кнопка нажимается пальцем полностью, т. е. переводится из одного крайнего положения (отжата) в другое (нажата). Чего мы не можем отследить визуально, так это когда именно нажимаемая кнопка замыкает 2 контакта геймпада. Точно можно сказать, что где-то между этими двумя крайними положениями, но в какой именно момент - сказать нельзя. А теперь немного математики. Предположим, я буду снимать на камеру с 120 кадров в секунду (а на нее я снимать и буду), тогда 1000 мс разделить на 120 кадров = 8,(3) мс. Один кадр длится 8,(3) мс - это предел точности наших измерений (пока что). Теперь, предположим, я могу нажать-отпустить кнопку геймада 5 раз в секунду, если не буду убирать с нее палец. Пять раз в секунду - это очень быстро, не так ли? В таком случае один цикл нажать/отпустить у нас займет 1000 мс разделить на 5 раз = 200 мс. Положим, что длительность нажатия у нас равна длительности отпускания, тогда нажатие кнопки у нас происходит 200 мс / 2 = 100 мс. Сто миллисекунд нам нужно для того, чтобы перевести кнопку из состояния "не нажата" в состояние "нажата". Причем, когда именно она замкнет контакты геймпада: в начале нажатия, в середине или в конце - мы не знаем. Таким образом, мы получаем погрешность измерения равной 100 мс. С учетом того, что инпут лаг оригинальной NES равен примерно 35 мс, а SNES и SMD - 50 - 70 мс, я считаю такую погрешность абсолютно не приемлемой. А если, предположим, мы нажимаем на кнопку не 5, а 3 раза в секунду (что тоже, я считаю, немало), то погрешность измерений вырастает до (1000/3)/2 = 167 мс. Поэтому, нам нужно точно знать момент, когда кнопка замкнула контакты геймпада, но как это сделать?
Что сделал я
К этому моменту мне пришла идея о том, что параллельно контакту кнопки геймпада можно подключить светодиод и вывести его на проводе наружу геймпада. И по зажиганию светодиода определять, что контакты замкнулись и сигнал пошел. Тогда я думал, что я самый умный и что использовать светодиод я придумал первым. Чуть позже я понял, что жестоко ошибался))).
Методология тестирования
На целевой платформе (во всех случаях это были ПК, в большинстве случаев - под Windows) запускался RetroArch версии 1.8.4 stable. К ПК подключался геймпад Defender Vortex с присобаченным к кнопке R1 красным светодиодом. Почему именно R1? Просто к ней мне было удобней всего подпаяться. Светодиод был вынесен из корпуса геймпада на красном проводе, длиной примерно 30 см. Провод со светодиодом располагался так, чтобы светодиод находился внизу монитора и при съемке попадал в кадр. Съемка велась на смартфон Motorola, который умеет в slow motion. т. е. он снимает видео в 120 fps, затем отснятое сохраняет в файл с уже 30 fps, таким образом получая замедление в 4 раза. Длительность одного кадра видео будет 1000 мс разделить на 120 кадров в секунду = 8,(3) мс. Эмулируемая платформа - NES. Используемый ROM - Super Mario Bros (World). Ядра (они же эмуляторы, они же cores) использовались все, способные работать с опцией run-ahead из доступных в каждом конкретном порте RetroArch. Да, ретроарч одной и той же версии, но собранный под разные ОС имеет разный список поддерживаемых ядер. Кнопке R1 в ретроарче было переназначено действие кнопки A, в Super Mario Bros - это прыжок.
Итак, запускался ром, запускалась игра, запускалась видеосъемка. Затем кнопка R1 нажималась, Марио подпрыгивал вверх и приземлялся обратно, кнопка отпускалась. Так повторялось 10 раз, иногда больше. Затем видео отсматривалось покадрово и велся подсчет кадров с момента зажигания светодиода до момента начала движения спрайта персонажа. Это и есть инпут лаг. Для каждой серии экспериментов приводится задержка минимальная/максимальная/средняя в кадрах/миллисекундах.
Платформы, на которых проводилось тестирование
Глядя на разношерстный зоопарк железа и операционных систем, которые я использовал для тестирования, кому-то могло показаться, что я хватал все оборудование, какое попадалось под руку. Вам не показалось, так оно и было)
Результаты тестирования
1) Железо: ноутбук Toshiba Sattelite L30-113. ЦП: Intel Core2Duo T2450 2,0 ГГц; ОЗУ: 2 Гбайт; Видео: ATI Radeon XPress 200M.
ОС: Windows 7 Ultimate SP 1 32 bit. Результаты (минимальный/максимальный/средний инпутлаг, кадров/миллисекунд):
Nestopia (UE): 4 кадра/33 мс / 9 кадров/75 мс / 7 кадров/56 мс.
FCEUmm: 6 кадров/50 мс / 12 кадров/100 мс / 10 кадров/80 мс.
QuickNES: 5 кадров/42 мс / 10 кадров/83 мс / 8 кадров/65 мс.
Emux NES: нет поддержки run-ahead, инпут лаг не замерялся.
Mesen: при включении run-ahead начались жуткие тормоза изображения и звука, fps просел до 30 с копейками, инпут лаг не замерялся.
2) Железо: Монитор Acer AL1717F, LCD, 17 дюймов, 4:3, 1280х1024, время реакции (заявленное) 5 мм, VGA.
ЦП: Intel Pentium CPU G4560 3,5 ГГц; ОЗУ: 4 Гбайт; Видео: Intel HD Graphics 610; НЖМД: Toshiba DT01ACA050.
ОС: Win 10 Professional 1809, 17763.1039 64 bit. Результаты (минимальный/максимальный/средний инпутлаг, кадров/миллисекунд):
Nestopia (UE): 9 кадров/75 мс / 20 кадров/167 мс / 12 кадров/99 мс.
FCEUmm: 9 кадров/75 мс / 13 кадров/108 мс / 11 кадров/91 мс.
Emux NES: нет поддержки run-ahead, инпут лаг не замерялся.
Mesen: ром запустился, изображение и звук были в норме, fps близко к 60, игра работала нормально, но я накосячил с видеозаписью) Переснимать не стал.
3) Железо: ноутбук Lenovo B590. ЦП: Intel Core i3-2348M 2,3 ГГц; ОЗУ: 8 Гбайт; Видео: NVidia GeForce 610M; НЖМД: WDC WD5000LPVT-08G33T1.
ОС: Windows 7 Prof SP1 64 bit. Результаты (минимальный/максимальный/средний инпутлаг, кадров/миллисекунд):
FCEUmm: 8 кадров/67 мс / 14 кадров/117 мс / 10 кадров/86 мс
Mesen: 10 кадров/83 мс / 13 кадров/108 мс / 12 кадров/98 мс
Nestopia UE: 7 кадров/58 мс / 14 кадров/117 мс / 10 кадров/82 мс
QuickNES: 9 кадров/75 мс / 14 кадров/117 мс / 11 кадров/89 мс
4) Железо: полноутбука IRU Bravo-4315 (отсутствует крышка с матрицей); ЦП: Intel Pentium 4 (Prescott) 2,8 ГГц; ОЗУ: 768 Мбайт; Видео: дискретное, какой-то Radeon 9x; НЖМД: какой-то IDE; Монитор: Samsung SyncMaster 757MB (ЭЛТ). ОС: Linux Xubuntu 18.04 LTS. Результаты (минимальный/максимальный/средний инпутлаг, кадров/миллисекунд):
FCEUmm: 5 кадров/42 мс/ 13 кадров/108 мс / 9 кадров/77 мс
Nestopia UE: 5 кадров/42 мс / 11 кадров/92 мс / 9 кадров/74 мс
QuickNES: 4 кадров/33 мс / 12 кадров/100 мс / 8 кадров/65 мс
Выводы
Изначально это тестирование задумывалось мной как сравнение инпут лага ретроарча с включенной опцией "run-ahead" с ретроарчем же, но без использования этой фичи. Но, как в последствии я понял что, в таком подходе не очень много смысла. Ибо run-ahead убирает встроенный инпут лаг самой игры (рома), а не эмулируемой консоли. Для подавляющего большинства ромов для NES - это 1 кадр = 17 мс при 60 fps. Это немало и это действительно то, что доступно ретроарчу и недоступно оригинальным консолям. Но, даже при всем этом, по величине инпут лага эмуляторы NES никак не могут тягаться на равных с оригинальными 8-битными консолями от Nintendo. Поэтому тестирование превратилось в попытку выяснить, насколько максимально малым может быть инпут лаг при использовании ретроарча, на что способен ретроарч хотя бы "в прыжке и из последних сил".
Можно ли запускать ромы от NES/Famicom и комфортно в них играть, используя эмуляторы, входящие в состав Retroarch? Да, можно. Вполне достижимо снижение инпут лага до уровня, характерного для реальных игровых консолей четвертого поколения (Sega Mega Drive/Genesis, SNES) - 50 - 70 мс. Если боги будут на вашей стороне.
Правда ли что при эмуляции NES/Famicom посредством RetroArch возможно добиться инпут лага даже меньшего, чем на оригинальных консолях? Мне этого не удалось. Я не встречал какие-либо подтвержденные данные, свидетельствующие о том, что это кому-то удалось.
Послесловие
Немного (сильно) сумбурно получилось, да. Но, в любом случае, спасибо, что дочитали этот нудно-экспрессивный пост до конца). Надеюсь, информация изложенная здесь, будет кому-нибудь полезной. Всем добра, хороших игр и увлекательных исследований! Пока.