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) теперь поддерживаются минимально и работают как простое нажатие (раньше вообще пропускались).

Оставьте первый комментарий

Оставить комментарий

Ваш электронный адрес не будет опубликован.


*