Skip to content

Building a ROM

Rodrigo Alfonso edited this page May 9, 2024 · 112 revisions

TL;DR

This is the easiest way!

  • 💻 Get a Windows machine and download the portable song importer
  • 📂 Extract the ZIP file into a folder
  • 📦 Drag and drop a folder with StepMania/StepF2 songs to the .bat file
    • ⚠ The path to the folder cannot contain space characters
  • ✔ Your ROM will be piugba.out.gba

(1) Install

  • Install the required dependencies listed in README.md. Though the instructions are made for Windows, all the tools are available for Linux distributions. VSCode is not necessary if you don't plan to change the code.
  • Check if everything is working correctly by running ./scripts/toolchain/check.sh
  • Run ffmpeg -v, it should say version 3.3.3. If it doesn't, add the ffmpeg executable included in scripts/toolchain/programs at the start of your PATH environment variable

(2) Import songs

  • Create in src/data/content/songs one folder per song, including:
    • one .mp3 file with the song (flac/ogg also work)
    • one .png file with the background
    • one .ssc file with the charts
  • Optional: If you want to support background videos, add a src/data/content/songs/_videos folder with .mpg files (mpeg/mp4 also work)
    • Each file name must match the song name (e.g. if the audio file is 101.MP3, the video should be 101.MPG)
  • Recommended: Add a ROM name to src/data/content/songs/romname.txt and it'll appear on the start screen (maximum is 12 characters)
  • Run make import to create the game's database in src/data/content/files.gbfs
    • To include high-quality audio, add HQAUDIOENABLE=true
    • To include background videos, add VIDEOENABLE=true

The import process runs one song at a time, allowing users to spot errors and observe results for each track, though this method can be slow. Once you've verified everything works as expected, you can speed up the process by using make import FAST=true.

Campaign vs Arcade builds

⚠️ Keep in mind that to build full ROMs (with Campaign mode), your songs need to have at least 3 charts for Normal, Hard and Crazy. Otherwise, you will get a cannot_autoset_difficulty error. If you don't care about Campaign mode, just run make import ARCADE=true and in the next step, use one of the Arcade prebuilt ROMs.

The ROM ID

The import process generates a file in src/data/content/songs/romid.u32. Next time you run make import, it'll reuse that file and the generated ROM will be savefile-compatible (and multiplayer-compatible).

⚠️ If you change the number of songs or its order, you must delete it, or the song count will be wrong and you will get a song_count_doesnt_match_rom_id error.

(3) Compile

Easy way (package existing build)

  • Download a clean build from Releases, pick one variant, and copy that file to the project's root directory as piugba.gba
  • Run make package. The output will be piugba.out.gba

Hard way (build from source)

  • Compile game assets:
    • make assets
      • This will generate a folder with compiled sprites, located at src/data/content/_compiled_sprites
  • Compile/package the game:
    • make restart ENV=production (or make restart for development)
  • Fix possible compilation/linker errors.

Arcade builds

If you want to quickly import songs without setting up a chart for each difficulty level, you might want to create an Arcade build. Just add ARCADE=true to both your importing and compilation commands. Example:

make import ARCADE=true
make restart ENV=production ARCADE=true

Correcting offsets

If a song doesn't feel right or you're getting too many greats/goods instead of perfects, it may be out of sync. To fix that, you can calculate a new offset when playing.

  • ⚠️ If the arrows arrive too soon, you need a negative offset.
  • ⚠️ If the arrows arrive too late, you need a positive offset.

Easy way (automatic apply)

  • Enable Offset editing in the Admin menu.
  • Use SELECT + L/R on the Song Selection screen to adjust the chart offset, which will be recorded in the save file. In this mode, you can see which charts have different offsets, as they are labeled as 'a', 'b', etc. If the charts are labeled as '!', it means that they all have the same offset.
  • Once all charts feel OK, create a file called offsets.pofs file in the songs' directory, with the following format:
SoNg TiTlE 1[s13]=-40
song title 2[s06]=-16
really broken song[s19]=-48
really broken song[s21]=80
really broken song[d22]=-32
really broken song[s23]=0
really broken song[d99]=delete
song title 3[s08]=-16
song title 3[m07]=-20
song title 3[d99][1]=-16

(s means single, d means double, m means multiplayer)

The importer will read this file and apply corrections to the final ROM. It'll also copy the corrected offsets to similar charts that share the same original offset. For example: if a song has three charts (s12, s18, and d23) with offset=-2.21, but when you play you realize that it's off by 100 milliseconds, you can set the correction for one of them:

the song[s18]=-100

...and since s12 and d23 have the same original offset, they'll also receive the same -100ms correction, unless you specify a custom one in the offsets file.

  • The name is case-insensitive but has to match the one that appears in the importer's output (the name shown in the game).
  • You can use the delete keyword to remove a broken chart.
  • You can add an optional subindex like d99[1] to specify which level-99 chart you are targeting.

Save and run make reimport to import the song library again without recompiling.

🌎 Additionally, you can add another file called global-offset.pofs containing a number of milliseconds (either positive or negative), and this global offset will be applied to the whole song library.

Automatic offsets.pofs

If you don't feel like writing the offsets.pofs file manually, you can dump your save file to your songs directory as offsets.sav and run:

node scripts/importer/src/helpers/dumpOffsetsFromSaveFile.js

It will print the offset corrections automatically, based on your custom offsets.

Hard way (editing SSC files manually)

To do it manually, run the game in development mode:

  • Use B+START and B+SELECT to apply -8ms and +8ms offsets (which will make arrows appear later and earlier, respectively)
    • The current offset will appear as a fixed combo value (a red number means negative)
  • When you finish the song, remember the final offset in the combo value
  • Go to the song's file, look for the #OFFSET SSC tag, and add the offset you calculated (divided by 1000, so it's in seconds) to the current value. It will appear multiple times, one per chart. Only modify the chart you played
    • For example, if you corrected an s17 chart and ended up with a red combo value of 32: find the chart that says #METER:17, and look at its #OFFSET. If it has #OFFSET:-0.145500, you must set -0.145500 + (-32/1000) as the new offset ⇒ #OFFSET:-0.177500
  • Save and run make reimport to import the song library again without recompiling

Campaign builds

Adding bosses

The import script generates a list with all the songs and their assigned levels, sorted by level and complexity.

By default, it makes the last song of each level a "boss fight", setting the BOSS channel and adding some mods. You can customize your ROM by disabling auto-bosses (make import BOSS=false) and adding the tags by yourself.

You need to use the custom #PIUGBA SSC tag. See the example in SSC format. The message will be shown before the song and all the mods will be applied only in Campaign mode.

Reassigning levels

If you don't like how the importer assigned difficulty levels to a particular song, you can set them manually:

  • Play the song in the Arcade mode and choose 3 levels
  • Find those 3 charts in the SSC file and change their #DIFFICULTY SSC tag to NORMAL, HARD, or CRAZY

Reordering songs

To reorder a song at a difficulty level, the easiest way is to use a #PIUGBA_ORDER SSC tag to override the song's #METER (level). This will keep the song's level untouched and use the new order tag when sorting.

Bonus songs (remixes)

You can put bonus songs in a folder named _bonus inside your regular songs folder, and these will be available after finishing the DeathMix challenge.