Written in C โ bare-metal arm-none-eabi on GBA (no SDK, just the hardware), plus native Nintendo DS / DSi (devkitARM + libnds), Nintendo 3DS / 2DS (devkitARM + libctru, with stereoscopic 3D), and Sony PSP (pspdev / pspsdk) builds, all driven from one shared game core.
| ๐ฏ Four targets, one core | A portable game core behind a small platform layer builds a bare-metal GBA .gba, a native DS/DSi .nds, a 3DS/2DS .3dsx, and a Sony PSP EBOOT.PBP โ identical physics, menus, and progression on all four. |
| ๐ Authentic physics | Verlet-integrated bike dynamics ported from the original โ 3 engine leagues (100cc ยท 175cc ยท 220cc). |
| ๐ง Articulated rider | A jointed sprite (legs, torso, arm, helmet) that leans with the bike. |
| ๐๏ธ Native-res rendering | Software rasteriser into a per-target framebuffer, fixed 60 Hz simulation fully decoupled from the frame rate, filling each screen 1:1 โ 240ร160 (GBA), 256ร192 (DS), 400ร240 (3DS), 480ร272 (PSP). |
| ๐ฅ๏ธ Dual-screen | On DS and 3DS the bottom screen carries the track-detail card and a live in-game progress minimap instead of crowding the playfield. |
| ๐ฅฝ Stereoscopic 3D | The 3DS top screen renders once per eye with per-layer parallax (track, bike, flags pop at different depths), dialed in live by the 3D slider. |
| ๐จ Customization | Recolor the helmet, rider suit, and bike from a shared palette, with a live preview; choices persist with your save. |
| ๐ Progression | The first track is open by default; finishing a track unlocks the next, and clearing a league unlocks the next league. |
| โฑ๏ธ Best times & cursor | Per-track scoreboard plus the last track opened per league, persisted per platform โ GBA battery SRAM, or an SD-card / Memory Stick save file on DS/3DS/PSP. |
| โก Fast navigation | Hold Up/Down (or the analog stick) to auto-scroll long league/level lists. |
| ๐ Sound | Crash SFX on every target โ GBA DirectSound, DS ARM7 soundPlaySample, 3DS ndsp, PSP sceAudio. |
| โ๏ธ Settings | Pick tilt buttons (D-pad or L/R shoulders), toggle sound, reset progress (with confirmation), and an About screen. |
| ๐๏ธ Platform-aware UI | Menus center and scale to each screen โ the PSP draws the interface at 2ร and shows its โ / โฏ buttons in prompts instead of A/B. |
| ๐งฉ Mod packs | Drop a levels/*.mrg file in and each build emits a separate ROM per mod with its name baked onto the menu. |
sudo apt update
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi make๐ Regenerating the asset/sound headers is optional โ they're committed. If you want to, install Python with
pillowandminiaudio:pip install pillow miniaudio
make # one ROM per levels/*.mrg โ release/gba/ReGravity_Defied_<mod>_v<ver>.gba
make assets # regenerate src/generated/gd_assets.h + gd_sound.h from assets/
make debug # build with mGBA debug logging (-DDEBUG)
make clean # remove build/gba and release/gbaEvery target writes its ROMs to release/<platform>/ (objects go under build/<platform>/).
Run a release/gba/ReGravity_Defied_*.gba in any GBA emulator (mGBA, VisualBoyAdvance, no$gba)
or on real hardware via a flashcart. SRAM saves require an emulator/flashcart with save support.
๐ก WSL tip: if a Windows emulator has the ROM open, the
.gbafile is locked andmakecan't overwrite it โ close the emulator before rebuilding.
The DS build needs the devkitPro DS toolchain (devkitARM + libnds + calico + libfat):
# install devkitPro pacman per https://devkitpro.org/wiki/Getting_Started, then:
sudo dkp-pacman -S nds-dev
export DEVKITPRO=/opt/devkitpro
make -f Makefile.nds # one .nds per levels/*.mrg โ release/nds/ReGravity_Defied_<mod>_v<ver>.nds
make -f Makefile.nds cleanRun a release/nds/ReGravity_Defied_*.nds in a DS emulator (melonDS, DeSmuME) or on real
hardware โ flashcart on DS/DS Lite, or directly on a homebrew-enabled DSi/3DS (the
.nds is flagged DSi-compatible). Saves are written to the SD card as regravity.sav.
๐ The DS/DSi target is new: it builds, links, and packages a valid
.nds, but hasn't yet been verified on hardware/emulator. The GBA build remains the primary, battle-tested target.
The 3DS build needs the devkitPro 3DS toolchain (devkitARM + libctru):
# install devkitPro pacman per https://devkitpro.org/wiki/Getting_Started, then:
sudo dkp-pacman -S 3ds-dev
export DEVKITPRO=/opt/devkitpro
make -f Makefile.3ds # one .3dsx per levels/*.mrg โ release/3ds/ReGravity_Defied_<mod>_v<ver>.3dsx
make -f Makefile.3ds icon # (optional) generate the HOME-menu app icon (needs Pillow)
make -f Makefile.3ds cleanRun a release/3ds/ReGravity_Defied_*.3dsx in Citra or on a homebrew-enabled 3DS/2DS (copy
to the SD card and launch from the Homebrew Launcher). Saves are written to the SD
card root as regravity_defied.sav.
The 3DS is the second dual-screen target, so it reuses the DS layout โ the track-detail card and the in-game progress minimap live on the bottom screen. On top of that it drives the autostereoscopic top screen: the flat 2D scene is rendered once per eye with per-layer horizontal parallax (the track sits at the screen plane, the bike floats toward you, and the flags pop out the most โ a pop-up-book depth). Slide the 3D slider up to dial in the effect; at zero the image is a comfortable flat 2D. The Circle Pad mirrors the D-pad for steering.
๐ The 3DS target is new: it builds against libctru and packages a valid
.3dsx, but hasn't yet been verified on hardware/emulator. The GBA build remains the primary, battle-tested target.
The PSP build needs the pspdev toolchain (psp-gcc + pspsdk + mksfoex + pack-pbp):
# install pspdev per https://github.com/pspdev/pspdev (or `brew install pspdev`),
# then make sure psp-config is on PATH:
make -f Makefile.psp # per levels/*.mrg: a game folder + a .zip of it
make -f Makefile.psp icon # (optional) regenerate the 144ร80 Game-menu icon (needs Pillow)
make -f Makefile.psp cleanEach mod is emitted as a ready-to-run game folder,
release/psp/ReGravity_Defied_<mod>_v<ver>/EBOOT.PBP, with a 144ร80 ICON0.PNG
(generated from assets/icon.jpg) so the entry shows artwork in the Game menu โ
plus a same-named .zip of that folder (ReGravity_Defied_<mod>_v<ver>.zip,
containing <game>/EBOOT.PBP) for distribution. Run an EBOOT.PBP in the PPSSPP
emulator, or install it on a homebrew-enabled PSP (see Install).
The PSP has a single screen, so it uses the GBA single-screen layout
(with the interface drawn at 2ร and reflowed for the larger panel), rendered at the
LCD's native 480ร272. Cross accelerates, Circle/Square brake, the D-pad or analog
stick lean/steer, and the shoulder triggers are L/R โ and the on-screen prompts show
the PSP's โ / โฏ glyphs instead of A/B. Saves are written to the Memory Stick at
ms0:/PSP/SAVEDATA/regravity_defied.sav.
๐ The PSP target is new: it builds against pspsdk and packages a valid
EBOOT.PBP, but hasn't yet been verified on hardware/emulator. The GBA build remains the primary, battle-tested target.
Each build lands in release/<platform>/. Pick your mod's ROM and follow the steps
for your device. All targets run in an emulator too (see each build section above).
- Copy the
.gbaonto a GBA flashcart's SD/CF card (EZ-Flash, EverDrive-GBA, โฆ). - Launch it from the cart's menu.
- Saves need a flashcart with SRAM save support; progress is stored in the ROM's battery SRAM.
- DS / DS Lite: copy the
.ndsto a DS flashcart (R4, etc.) and launch from its menu. - DSi / 3DS (homebrew): the
.ndsis DSi-flagged โ run it from the SD card via TWiLight Menu++ or nds-bootstrap. - Saves are written to the SD card as
regravity.sav.
- On a homebrew-enabled console, copy the
.3dsxto the SD card's/3ds/folder. - Launch it from the Homebrew Launcher.
- Saves are written to the SD card root as
regravity_defied.sav.
- On a CFW / homebrew-enabled PSP, extract the
.zipintoms0:/PSP/GAME/on the Memory Stick (it already contains aReGravity_Defied_<mod>_v<ver>/EBOOT.PBPfolder, so it lands atms0:/PSP/GAME/ReGravity_Defied_<mod>_v<ver>/EBOOT.PBP). - The entry appears in the PSP's Game menu with its icon; launch it there.
- Saves are written to
ms0:/PSP/SAVEDATA/regravity_defied.sav.
Equivalently, copy the unzipped
release/psp/ReGravity_Defied_<mod>_v<ver>/folder directly intoms0:/PSP/GAME/โ the.zipis just that folder, packaged.
| Button | Action |
|---|---|
| A | Accelerate ยท confirm |
| B | Brake ยท back |
| โ / โ | Lean (D-pad tilt mode) |
| L / R | Lean (shoulder tilt mode) |
| โ / โ | Navigate menus ยท hold to scroll faster |
| START | Select ยท start |
| SELECT | In-game: track menu ยท League menu: settings |
The source tree is split by responsibility: a portable core, the generated
asset headers, and one platform backend folder per target. The core talks to
each backend only through the small interface in core/platform.h, so adding a
target is a new platform/<name>/ folder plus a Makefile.
src/
โโโ core/ portable game code + the platform interface (built for every target)
โ โโโ main.c game loop, state machine, menus, progression
โ โโโ physics.c/.h bike physics + rider rendering
โ โโโ graphics.c/.h drawing primitives + back buffer
โ โโโ level.c/.h track decoding and rendering
โ โโโ save.c/.h save logic (progress, best times, cursor)
โ โโโ platform.h color/keys/timing + platform_init/keys/timer/vsync interface
โ โโโ sound.h SFX interface
โ
โโโ generated/ committed, tool-generated (do not hand-edit)
โ โโโ gd_assets.h sprites/images (tools/convert_assets.py)
โ โโโ gd_sound.h crash SFX PCM (tools/convert_sound.py)
โ โโโ gd_sprites.h flag sprites
โ
โโโ platform/ one hardware backend per target (platform_/graphics_/sound_/save_)
โโโ gba/ โฆ_gba.c + gba.h (register map) + crt0.s (startup) + gba.ld (linker script)
โโโ nds/ โฆ_nds.c LCDC framebuffer ยท libnds sound ยท libfat SD save
โโโ 3ds/ โฆ_3ds.c libctru gfx + stereo 3D ยท ndsp sound ยท stdio SD save
โโโ psp/ โฆ_psp.c GU 480ร272 present ยท sceAudio SFX ยท Memory Stick save
Makefile GBA ยท Makefile.nds DS/DSi ยท Makefile.3ds 3DS/2DS ยท Makefile.psp PSP
build/<platform>/ intermediate objects release/<platform>/ final ROMs
assets/ source PNGs + sound/ + icon.jpg; tools/*.py bake them into src/generated/ + the DS/3DS icons
levels/*.mrg track-data mod packs โ one ROM is built per file
Each levels/<name>.mrg is compiled into its own build/gba/<name>/ directory with
MOD_NAME baked in, embedded via objcopy, and linked into a standalone
release/gba/ReGravity_Defied_<name>_v<ver>.gba. The mod name shows up on the league
screen, so you can ship a classic ROM, a 1000-track ROM, or your own pack side by side.
Makefile.nds, Makefile.3ds and Makefile.psp mirror this exactly for the DS, 3DS
and PSP, producing one .nds / .3dsx / game-folder EBOOT.PBP per mod under
release/<platform>/.
The game logic, rendering primitives, menus and physics are identical on all four โ only the thin hardware backends change:
| Game Boy Advance | Nintendo DS / DSi | Nintendo 3DS / 2DS | Sony PSP | |
|---|---|---|---|---|
| Toolchain | bare-metal arm-none-eabi, custom crt0.s + gba.ld |
devkitARM + libnds + calico | devkitARM + libctru | pspdev + pspsdk |
| CPU | ARM7TDMI @ 16.78 MHz | ARM9 @ 67 MHz (+ ARM7 for sound) | ARM11 @ 268 MHz | MIPS Allegrex @ 222โ333 MHz |
| Display | Mode 3 bitmap, DMA blit | LCDC framebuffer, native 256ร192 full-screen | 320ร240 centered on the 400-wide top screen; BGR555โRGB565 rotated present | VRAM framebuffer, native 480ร272 (512 stride), 5551 present |
| Second screen | โ | detail card + in-game minimap | detail card + in-game minimap | โ |
| Stereoscopic 3D | โ | โ | per-layer parallax, rendered once per eye, scaled by the 3D slider | โ |
| Frame timing | fixed 60 Hz sim; ~30 fps render | fixed 60 Hz sim; 60 fps render | fixed 60 Hz sim; 60 fps render | fixed 60 Hz sim; 60 fps render |
| Sound | DirectSound FIFO (hand-fed) | soundPlaySample (ARM7) |
libctru ndsp |
sceAudio SRC (worker thread) |
| Save | battery SRAM | regravity.sav on SD via libfat |
regravity_defied.sav on SD via stdio |
regravity_defied.sav on Memory Stick |
Open source, released for educational purposes. This is a fan reimplementation of Gravity Defied โ the original game and its assets belong to their respective owners.