Как ускорить / замедлить «время» приложения - PullRequest
4 голосов
/ 30 марта 2010

Полагаю, я не говорю это прямо в названии. Что я собираюсь сделать, это подключиться к некоторому системному API, например, прерывание по времени происходит каждый раз, когда каждое приложение в операционной системе интерпретирует время, и сделать так, чтобы вызов приложения к этому API возвращал больший / меньший результат. Таким образом, с точки зрения приложения время ускорилось или замедлилось. Я нашел какое-то приложение на Windows, делающее это, может кто-нибудь дать мне несколько советов о том, как реализовать это в Mac OS X?

Ответы [ 4 ]

3 голосов
/ 21 мая 2010

Ваш вопрос нужно разделить на две части:

  1. Какой источник значений времени используется многими приложениями?
  2. Как мне перехватить этот источник?

Ответ на 1) (примерно в порядке важности):

  • Системные часы, считанные gettimeofday (которые, в свою очередь, используются NSDate, CFAbsoluteTime, ...)
  • Часы звуковой карты. Многие мультимедийные приложения синхронизируют визуальные эффекты со звуком и используют звук в качестве источника времени.
  • Видео часы (считая vsyncs)
  • Счетчики тиков процессора, прерывания и т. Д.
  • Только продвижение счетчика программ (скорость выполнения).

Edit:

  • Функции синхронизации Маха. Спасибо, @tc, за то, что указал на это.

Перехват gettimeofday относительно прост: просто создайте динамическую библиотеку, содержащую функцию с тем же именем и сигнатурой, что и у исходного gettimeofday (см. #include <sys/time.h>). Эта функция должна возвращать любое значение, которое вы хотите для времени.

Чтобы использовать эту специальную функцию gettimeofday в приложении, запустите ее в Терминале, как в:

DYLD_INSERT_LIBRARIES=/path/to/myGetTimeOfDay.dylib /Applications/TextEdit.app/Contents/MacOS/TextEdit

Конечно, ваш dylib должен соответствовать архитектуре приложений.

2 голосов
/ 25 мая 2010

В дополнение к исправлению gettimeofday () (или как бы он ни вызывал это изнутри), вам также потребуется исправление mach_timebase_info (): оно возвращает частоту mach_absolute_time (), которая используется практически везде, где системный API имеет отметка времени, которая является «временем с момента загрузки». Конечно, вы также можете исправлять mach_absolute_time (), но это, вероятно, будет намного дороже. См. QA1398 для некоторых деталей (обратите внимание, что строка elapsedNano = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom подвержена переполнению).

(Соответствующая функция POSIX - clock_gettime(CLOCK_MONOTINIC, &result). Непонятно, почему OSX не реализует это.)

2 голосов
/ 20 мая 2010

Я не разработчик для OS X, поэтому не могу дать вам подробности. Но я знаю Windows и могу догадаться, как это можно реализовать - вы можете преобразовать некоторые методы.

В качестве иллюстрации предположим, что большинство программ, которые хотят следовать абстрактному ходу времени в Windows, используют GetTickCount . Это возвращает количество миллисекунд с момента запуска системы. (Существуют и другие API, которые может использовать приложение, но метод остается тем же.)

Чтобы изменить время, отображаемое для приложения, необходимо изменить значения, возвращаемые этой функцией времени. (например, умноженное на коэффициент), поэтому мы создаем функцию-обертку для применения преобразования:

  DWORD GetTimeWarpTickCount()
  {
      static double factor = 2.0;
      return (DWORD)(GetTickCount()*factor);
      // simple implementation - you can be more sophisticated than this 
      // to preserve accuracy if necessary
  }

После того, как вы закодировали функцию, используйте перехват , чтобы заменить оригинальную функцию Win32 на вашу собственную. Хукинг можно выполнять для каждого приложения, поэтому вы можете локализовать изменения времени для конкретных приложений.

Итак, короче говоря, если есть способ переопределить основные функции времени, предоставляемые приложениям OS X, то вы можете применить ту же процедуру.

1 голос
/ 19 мая 2010

Если это ваше приложение, просто направьте все ваши запросы времени через написанную вами функцию, которая имеет скаляр. Чтобы сделать что-то похожее на произвольное приложение, вставьте некоторый код и, так сказать, исправьте ловушку. Я думаю, что mach-inject все еще существует, и есть другие подобные инструменты, такие как ape , которые придают ему приятное лицо. Даже если это ваше приложение, вы можете использовать такой подход в mach-inject для манипулирования результатом вызовов системного времени.

Все звонки с часами из какао и основного основания просачиваются в gettimeofday. Есть и другие способы отслеживания времени, но это хорошее начало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...