
JumpyBall
Port nativo de JumpyBall para PC.
JumpyBall
Port nativo basado en su ficha de origen.
README del repositorio
jumpyball-decomp
Порт игры JumpyBall (Windows Mobile / Pocket PC, экран 240x320) на C89. Хост-слой сменный: SDL2 (Windows, Linux, Android) или нативный Win32 API (Windows и Windows CE, GDI + waveOut, вообще без SDL2).
Логика восстановлена реверс-инжинирингом оригинальных JumpyBall.exe и hss.dll.
Код порта - собственный; из оригинальной поставки в репозиторий входят только
ассеты (BITMAP, Sounds, Musics), без бинарников и декомпилированных
исходников.
Что реализовано
- Псевдо-3D трасса с построчной проекцией, пять тем оформления
- Физика мяча, прыжок (в том числе автопрыжок), респавн
- Уровни, разблокировка, таймер и HUD оригинальным шрифтом
- Меню: главное, выбор уровня, настройки, «о программе»
- Настройка управления: мастер переназначения шести клавиш с сохранением в
keys.cfg - Звук: WAV-эффекты и музыка
.tkm(4-канальный ProTrackerM.K.) собственным плеером вjb_mod.c/jb_mod_effects.c
Сборка
Код - ANSI C (C89). Нужен компилятор C и, для бэкенда по умолчанию, SDL2.
CMake (Windows, Linux, куда угодно)
cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=Release
cmake --build build-cmake
SDL2 ищется тремя способами по очереди: find_package(SDL2 CONFIG),
find_package(SDL2), затем pkg-config sdl2. Если SDL2 лежит в нестандартном
месте, передайте -DCMAKE_PREFIX_PATH=<префикс sdl2>; для vcpkg -
-DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake.
BITMAP, Sounds и Musics копируются рядом с бинарником после сборки
(отключается -DJUMPYBALL_COPY_ASSETS=OFF).
На этой машине конфигурация с готовыми путями лежит в build-cmake.cmd.
Проверка на строгий C89
tools\c89check.cmd прогоняет все .c через clang (тот, что идёт с Visual
Studio Build Tools) с -std=c89 -pedantic-errors -Wall. Компоновки нет - это
проверка того, что код не опирается на расширения MSVC и соберётся другим
компилятором, в том числе gcc/clang под Linux.
jb_platform_win32.c и jb_audio_win32.c из этой проверки исключены: они
тянут windows.h, а заголовки SDK сами по себе не C89 (inline, long long,
безымянные union), так что -pedantic-errors срабатывает внутри SDK, не
доходя до нашего кода. Сам код этих двух файлов - тот же C89.
MSVC напрямую
Пути к MSVC и SDL2 заданы в начале build.cmd:
set VCVARS=D:\VS\BuildTools\VC\Auxiliary\Build\vcvars32.bat
set SDL=D:\vcpkg\installed\x86-windows
Поправьте их под свою машину и запустите:
build.cmd
Результат - build\jumpyball.exe вместе с SDL2.dll и ассетами.
Нативный Windows / Windows CE (без SDL2)
Весь платформенно-зависимый код сходится в одном заголовке jb_platform.h,
поэтому кроме SDL2-бэкенда есть второй, нативный: jb_platform_win32.c (окно,
ввод и вывод кадра через GDI) и jb_audio_win32.c (звук через waveOut). SDL2
при этом не нужен вообще - линкуются только gdi32, user32 и winmm.
Выбирается опцией -DJUMPYBALL_BACKEND=win32 (по умолчанию sdl2):
cmake -S . -B build-win32 -DCMAKE_BUILD_TYPE=Release -DJUMPYBALL_BACKEND=win32
cmake --build build-win32 --config Release
Кадр рисуется в DIB-секцию 16bpp RGB565 (CreateDIBSection с BI_BITFIELDS,
сверху вниз) и выводится в окно через BitBlt, а при масштабе больше 1 -
StretchBlt. Это тот же путь, что у оригинала через GAPI, только буфер отдаёт
GDI, а не драйвер экрана. Звук - четыре голоса WAV и музыка .tkm, смешанные
своим микшером и отданные в waveOut отдельным потоком-кормильцем; свой разбор
RIFF заменяет SDL_LoadWAV.
Кросс-сборка с Linux - mingw-w64:
sudo apt-get install gcc-mingw-w64-i686
sh tools/build_win32.sh
Для 64 бит - MINGW_PREFIX=x86_64-w64-mingw32 sh tools/build_win32.sh. Скрипт
зовёт CMake с tools/toolchain-mingw-w64.cmake; результат -
build-win32/jumpyball.exe, запускается и под Wine.
Windows CE
Для Windows CE нативный бэкенд - единственный вариант: SDL2 под CE нет. Собирается cegcc / mingw32ce:
CEGCC=/opt/mingw32ce TARGET=arm-mingw32ce sh tools/build_wince.sh
TARGET - arm-mingw32ce или i386-mingw32ce. Готовый каталог build-wince/
копируется на устройство целиком (например в \Program Files\JumpyBall): игра
ищет BITMAP / Sounds / Musics рядом с собой. Из зависимостей у неё только
coredll.dll.
Отличия ветки CE собраны под макросом JB_WINCE (jb_platform.h):
- окно всегда во весь экран (
WS_POPUP), масштаб подбирается автоматически; панель задач и кнопка SIP убираются черезSHFullScreen, который берётся изaygshell.dllдинамически - на образах без неё игра просто работает как есть - у CE только широкий API, поэтому все вызовы в бэкенде -
...W, а узкие строки расширяются на входе; в путях/заменяется на\ - у CE нет окружения процесса и
getenvв coredll, поэтому переменнаяJUMPYBALL_ASSETSтам не читается - собирается как
gnu89, а не строгийc89:inlineиспользуется вkfuncs.hсамой cegcc
Android (APK)
tools/android_prepare.sh собирает дерево Gradle в build-android/: скачивает
исходники SDL2 release-2.32.10, раскладывает шаблон android-project,
копирует в него jb_*.c / jb_*.h и ассеты в app/src/main/assets. Нужны JDK
17 и Android SDK с NDK (путь берётся из ANDROID_NDK_HOME / ANDROID_NDK_ROOT).
sh tools/android_prepare.sh
cd build-android && ./gradlew assembleDebug
Готовый APK - build-android/app/build/outputs/apk/debug/app-debug.apk,
универсальный: в одном файле лежат ABI armeabi-v7a, arm64-v8a, x86,
x86_64; minSdk 21, ориентация портретная.
Ассеты читаются прямо из APK через SDL_RWops, а keys.cfg пишется во
внутреннюю память приложения.
Game Boy Advance
У GBA нет ни SDL2, ни файловой системы, поэтому здесь свой нативный бэкенд
(jb_platform_gba.c) и ассеты всегда вшиты в ROM (JB_EMBED,
tools/gen_embed.py -> jb_embed_data.c). Собирается devkitARM:
sh tools/build_gba.sh
Результат - build-gba/jumpyball.gba, самодостаточный: грузится в эмулятор
(mGBA) или прошивается на картридж. По умолчанию тулчейн ищется в
/opt/devkitpro; переопределяется через DEVKITARM / DEVKITPRO.
Экран GBA - 240x160, а игра портретная 240x320, поэтому кадр рисуется в
режиме Mode 3 (линейный BGR555-фреймбуфер) с уменьшением x0.5 по обеим осям в
центр экрана; по бокам остаются чёрные поля. Время идёт от каскада Timer2/Timer3
(16384 Гц). Управление: крестовина - движение, A - прыжок, START - меню.
Звук на этом этапе выключен: jb_audio_gba.c - честная заглушка
(Platform_AudioInit возвращает 0, дальше Audio_Init сам не грузит сэмплы).
Настоящий звук через DirectSound (DMA-FIFO по таймеру) - следующая веха.
Сборки в CI
.github/workflows/build.yml собирает и прогоняет игру на семи
конфигурациях: Linux x86_64 и arm64 (плюс проверка на строгий C89), Windows x86
и ARM64 (обоими бэкендами - SDL2 и нативным), кросс-сборка нативного бэкенда
mingw-w64 с прогоном под Wine, Android APK, Windows CE (cegcc) и
GBA ROM через devkitARM. Настольные сборки проверяются
выгрузкой кадра в headless-режиме - файл обязан быть ровно 2403202 байта, -
APK проверяется на наличие libmain.so / libSDL2.so для всех четырёх ABI и
ассетов внутри архива, а .gba - на штамп заголовка (логотип Nintendo на
смещении 0x04) и размер (вшитые ассеты дают большой ROM).
Управление
По умолчанию: стрелки - движение, Space - прыжок, Escape - меню.
Переназначить можно в «Настройки» -> «Управление»: мастер по очереди просит
нажать клавишу для «влево», «вправо», «вверх», «вниз», «прыжок» и «меню»; уже
занятая клавиша не принимается.
На Android управление сенсорное: под кадром игры рисуется панель с крестовиной,
кнопкой прыжка и кнопкой меню, работает мультитач (например «вправо» и «прыжок»
одновременно). Размер кнопок считается от размера экрана, поэтому панель
одинаково умещается и на маленьком, и на большом устройстве. Аппаратная кнопка
«Назад» выходит из игры. Ту же панель можно посмотреть на десктопе - переменная
окружения JUMPYBALL_TOUCH=1.
Раскладка пишется в keys.cfg рядом с исполняемым файлом - шесть десятичных
кодов клавиш SDL, по одному на строку, в том же порядке. Это сознательное
отступление от оригинала: тот хранил keys.dat / keys2.dat с кодами VK в
кодировке «база 1000 + смещение 100», а коды VK не совпадают с кодами SDL, так
что переносить оригинальный формат было бы бессмысленно. Файл с непривязанной
или повторяющейся клавишей отбрасывается, и берутся значения по умолчанию.
В нативном бэкенде формат keys.cfg тот же, но коды в нём - VK (VK_LEFT,
VK_SPACE и так далее), как в оригинале, а не коды SDL. Два файла между
бэкендами не переносятся. Сенсорной панели в нативном бэкенде нет: она
нарисована через SDL_Renderer в jb_touch_sdl2.c, а у КПК под управление
есть свои аппаратные клавиши.
Чекпоинты
Чекпоинты берутся из битмапов уровней: чисто красный пиксель (RGB 255,0,0) в
BITMAP/309.bmp, 333.bmp, 334.bmp - это чекпоинт. Загрузчик карты пишет их
столбец и строку в таблицы, начиная с индекса 1, а респавн после падения
ставит мяч в последний чекпоинт, пройденный раньше текущей позиции камеры.
Второе сознательное отступление от оригинала: в оригинале обход таблицы чекпоинтов не ограничен их количеством и завершается только записью со строкой больше порога, поэтому в конце уровня он читает память за таблицей. Порт ограничивает обход числом фактически найденных красных пикселей.
Ассеты
BITMAP, Sounds и Musics лежат в репозитории и копируются в build\ при
сборке. Игра ищет их рядом с исполняемым файлом; путь можно переопределить
переменной окружения JUMPYBALL_ASSETS.
Аргументы командной строки
| Аргумент | Значение |
|---|---|
--level=N | стартовать сразу в уровне N |
--screen=N | стартовый экран меню |
--index=N | стартовая позиция в меню |
--unlocked=N | сколько уровней открыто |
N (число) | масштаб окна |
| путь | выгрузить кадр (RAW 16bpp) и выйти |
tools/
modtest.c - офлайн-проверка музыкального плеера: рендерит .tkm в WAV и
печатает peak/RMS и длительность, без звуковой карты. Сборка - tools\modtest.cmd,
запуск - modtest.exe <in.tkm> <out.wav> [volume] [loop].
c89check.cmd - проверка на строгий C89 (см. раздел «Сборка»).
build_win32.sh - кросс-сборка нативного (без SDL2) jumpyball.exe через
mingw-w64, build_wince.sh - то же для Windows CE через cegcc,
build_gba.sh - сборка GBA ROM через devkitARM,
toolchain-mingw-w64.cmake - файл тулчейна CMake, которым пользуется первый из
них.
android_prepare.sh - сборка дерева Gradle для APK (см. раздел «Сборка»).
Модификация уровней.
В игре есть всего три уровня в котором используются разные BITMAP. Так вот можно сами уровни редактировать используя Paint или другие редакторы. В основном уровни редактируются легко, 309.bmp, 333.bmp, 334.bmp это первый, второй, третий уровень. Их значения: черный - место где можно катать шарик, белый - вода, трава, по которому нельзя катать, красный - чекпоинт
Comentarios (0)
Inicia sesión para dejar un comentario.
Sé el primero en comentar sobre este juego.
