StepFucker — проходим треки в степмании на АААА

Написал на ассемблере программку для идеального прохождения треков в игре Stepmania.
Если вы не знакомы с такой игрой - посмотрите видео ниже, и поймёте ее суть - нажимать на 4 клавиши в ритм с песней руками или ногами (на специальных ковриках/автоматах).
Весь код программы я описывать не буду, опишу только новые особенности Win API, с которыми мне пришлось иметь дело во время написания.
Для начала, вот несколько скриншотов программы и видео ее работы:


Каждый степчарт (файл с указанием, как должны лететь стрелки), хранится в SM-файлах. Некоторые степчарты могут храниться в формате dwi, но его поддержку я не делал, да и смысла нет, т.к. Stepmania все равно конвертирует их в SM и складывает в /Путь_к_Моим_Документам/StepMania CVS/Cache/Songs/. Оттуда и можно брать SM-файлы.
Программа читает SM, обрабатывает его, и проходит трек с идеальной точностью. Есть единственная задача - попасть точно на первую стрелку, т.к. программа сама не умеет определять, когда начинать играть. Но если даже попадание не совсем точное, его можно отрегулировать горячими клавишами по ходу игры.
Программа эмулирует нажатия клавиш которые бы нажимал человек (они настраиваются), поэтому во время игры окно Stepmania должно быть активным, а управление программой (вкл-выкл, корректировка) производится с помощью горячих клавиш, которые также настраиваются.
Можно задать некоторый уровень ошибок, тогда при игре будут некоторые отклонения от идеала, и будет казаться, что играет человек.
Программа способна обрабатывать любые SM-файлы, в том числе и с изменяющимся ритмом (BPM), со стопами (STOPS).

Теперь - немного технической части.

1. Эмуляция ввода.
Эмуляция нажатия клавиш производилась с помощью функции SendInput. Отмечу, что для того, чтобы ввод работал и в приложениях DirectX, которые используют DirectInput (а степмания и является таковой), необходимо отсылать не виртуальные коды клавиш, а скан-коды. Чтобы получить скан-код клавиши по виртуальному коду, необходимо воспользоваться функцией MapVirtualKey.
Есть еще функция keybd_event для эмуляции ввода с клавиатуры, но она устаревшая и является просто переходником к SendInput.

2. Немного о таймингах.
Так как тайминги в степмании очень точные, пришлось отказаться от таких функций, как Sleep, SleepEx, GetTickCount, SetTimer - все они поразительно неточные.
Осталось выбрать между QueryPerformanceCounter (вместе с QueryPerformanceFrequency), timeGetTime и ассемблерной командой ldtsc.
Первая функция является самой точной, как правило, ее точность составляет 1/3.5 мс, но она и самая медленная, а во-вторых, с ней возникают трудности на многоядерных процессорах или на ноутбуках при изменении режима энергосбережения.
Эта функция запрашивает состояние независимого счетчика со своей не зависящей от частоты процессора тактовой частотой, но на деле частота от процессора зависит, а на многоядерных системах этот счетчик может вернуть состояние для каждого ядра по отдельности случайным образом (для устранения таких проблем есть приемы, но они не идеальны).
С командой ldtsc примерно та же ситуация. Она возвращает текущий такт процессора в int64. Но частота процессора может динамически меняться, поэтому использовать эту команду не следует.
В итоге я остановился на timeGetTime, установив с помощью timeBeginPeriod ее разрешение в 1 мс (минимально возможное). Кроме того, Stepmania также использует данную функцию.

3. FPU
Работа с FPU (Floating Point Unit, математический сопроцессор) на ассемблере очень уныла и громоздка. К счастью, в пакете MASM32 есть отличная удобная библиотека FpuLib для выполнения различных вычислений, сравнений, преобразований с числами REAL10 и DWORD (10 и 4 байта соответственно).
Хелп по этой библиотеке лежит в том же MASM32 в папке help.

Ну вот и все заметки, которые я хотел оставить по коду. Если есть какие-либо вопросы, можете оставлять их в комментариях.

В архиве с программой и исходниками есть еще файл windows.asm - я использовал макросы оттуда для создания юникодовых строк на русском языке в приложении.

Скачать программу и исходники: ZIP

UPDATE 14.09.2015: Добавлена возможность загружать степчарты большего размера, с бОльшим количеством стопов и изменений BPM. Теперь загружаются чарты, где каждый такт разделен на 96 частей. Роллы (rolls) теперь поддерживаются минимально и работают как простое нажатие (раньше вообще пропускались).

UPDATE 06.06.2016: English version is now available (thanks Kaimi): sfuck_en

StepFucker — проходим треки в степмании на АААА: 37 комментариев

    1. Во-первых, в самом MSDN написано.
      Про GetTickCount:

      The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds

      И про SetTimer:

      Because a timer's accuracy depends on the system clock rate and how often the application retrieves messages from the message queue, the time-out value is only approximate.

      И про Sleep(Ex):

      To increase the accuracy of the sleep interval, call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function to set the timer resolution to its minimum. Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application.

      SleepEx была самой точной из перечисленных Вами, но она не подошла чисто по алгоритму, так как задержки накапливались из-за различных операций с FPU и эмуляции ввода. Остальные функции имеют чересчур большие погрешности. Особенно SetTimer, особенно если он реализуется через WM_TIMER.

      А вот для функции timeGetTime() есть возможность установить разрешение таймера в 1 мс с помощью timeBeginPeriod, что вполне приемлемо.

      Разумеется, можно было бы использовать QueryPerformanceCounter/Frequency для получения значений с точностью до 1/3.5 мс или еще выше, но появится немало других проблем, да и надобности в такой точности нет.

    1. This software is very old, it'll be too difficult to support it now. By the way, these error texts are corrupted (this is the ANSI program, and error texts are in Russian, so they get corrupted when you launch the program in non-Russian Windows locale).

    1. Read my comment above:

      As I remember, this program supports .sm files only, .dwi format is not supported. If you have problems when opening .sm file, could you upload it somewhere, so I'll be able to take a look at it?

      These problems can only occur when you load SM file. We can't fix them without having the file that causes them. So please provide these files to us, so we're able to see what's wrong.

        1. Try the new version (just uploaded it, use the same download link). It can now open larger stepcharts, with more BPM changes and stops. Rolls are now supported and work as usual presses (previous version has no support for rolls at all).

            1. This probably will work with 5.0, too, as this cheat basically emulates keyboard input. You just have to set the keys correctly.

    1. О какой скорости идет речь? Все ведь зависит от BPM, переменный BPM там поддерживается, как и остановки

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *