Tutorial 09: Custom music
Make: Play an original audio file as Pallet Town's theme, then replace it with your own music.
Before you start: Intermediate, suitable for musicians after Tutorial 00. You need an audio editor only if you want to export your own track. No custom map or chiptune programming is required.
Game: Red, local single-player. Use a practice save for experiments. If file creation is new to you, start with Tutorial 00; unfamiliar words are in the Glossary.
1. Set up the files
Create a new tutorial_09 folder in your mod location. Disable earlier tutorial mods for this exercise. The starting state is this empty folder; the finished state is all the files below.
This is a mod folder, not the engine root. Do not replace the engine's own main.lua. Preserve filenames and avoid an extra .txt extension.
Finished folder layout:
mods/tutorial_09/
assets/town.wav
main.lua
manifest.json
Each link opens a complete file you can save at the matching path. The JSON and Lua are also printed in full below; do not append them to another lesson's entry function.
| File in this mod | Complete example |
|---|---|
assets/town.wav |
Download town.wav |
main.lua |
Download main.lua |
manifest.json |
Download manifest.json |
Save the audio download as assets/town.wav inside the mod. This supplied tone is original sample audio; it does not contain a game recording.
2. Describe the mod
Complete file: replace tutorial_09/manifest.json:
{
"id": "tutorial_09",
"name": "Tutorial 09",
"version": "1.0.0",
"entry": "main.lua",
"api": 2,
"games": [
"red"
]
}
id is the stable internal name, name is the label in MODS, and entry tells the loader which Lua file to open. games limits these examples to Red. Keep commas between JSON fields and no comma after the last field.
3. Write the change
Complete file: replace tutorial_09/main.lua:
return function(mod)
mod.content.music:register("Music_TutorialTown", {
file = mod.assets:path("assets/town.wav"),
})
mod.content.map_songs:override("PALLET_TOWN", "Music_TutorialTown")
end
Understand what you wrote
The music registration gives the audio file an ID. mod.assets:path("assets/town.wav") finds the file inside this mod. The map_songs override then tells Pallet Town to use that ID. Registering a song does not by itself choose where it plays.
The supplied town.wav is a short original generated tone, deliberately simple enough to recognize. First check that it plays, then replace it with your own exported WAV or supported Ogg audio. Changing the filename also requires changing the path in main.lua.
With only file, the engine loops that file. For a composed intro followed by a separate repeated section, add a loopFile path to the same music record and supply that second file. The intro plays once, then the loop repeats. Do not claim a smooth seam until you have listened through several repetitions.
Keep audio authoring separate from routing while learning: use a known-good file to verify the path, and a known-good map to verify where it plays. Then change the recording.
4. Load and check it
Save every file, restart the app, enable the mod for Red in the launcher's MODS panel, and launch. Resolve any load error before checking gameplay. Troubleshooting shows where errors appear. With default desktop bindings, A is Z/Enter/Space, B is X/Backspace, and Start is Escape/keypad Enter; use your configured controls if different.
Optional source-checkout validation
If you have Python 3, LuaJIT, and the engine source with Red imported, open a terminal in the engine root containing tools/. For a mod installed in that checkout's mods directory, run:
python3 tools/modkit.py validate tutorial_09 --base imported
If you saved it elsewhere, replace the mod ID with the quoted full path to its folder. A validation error identifies a file or content rule to fix; a pass means you can continue to the in-game checks. It does not prove rendering, sound, or the entire playthrough works. Packaged-app users can use MODS errors and the checkpoints without setting up these command-line tools.
Checkpoint
- Copy the supplied WAV into
assets/town.wav; confirm it is an audio file, not a saved web page or a text file renamed .wav. - Enable this mod, launch Red, and enter Pallet Town from a house. You should hear the short repeating sample instead of the normal town theme. Check the app's audio volume if silent.
- Export a short original tune, replace the WAV, save, and restart. Listen in Pallet Town through at least three loops; check for an unwanted pause or click at the seam.
- Enter a location with a different theme to confirm this example changes only the selected map's song. Disable the mod and restart to compare with the original town theme.
Common pitfalls
| What you see | What to check |
|---|---|
| Silence or a file-load error | Check assets/town.wav, the real file format, audio volume, and the mod's log error when entering the map. |
| New song is registered but never plays | Check the map_songs assignment and enter PALLET_TOWN again. |
| Click or gap on repeat | Edit the audio's loop seam in your audio editor; changing a registry ID cannot repair the waveform. |
For syntax, missing-file, and restart problems, use Troubleshooting. Compare the whole finished file before changing several things at once.
Undo and continue
Disable the mod and restart to compare with the original Red behavior. Keep a copy of your finished files if you want to return to them.
Optional: chiptunes and conditional themes
Audio Authoring retains the ChipAsm route for writing note events in Lua, including tempo, channels, labels, and loops. It is an alternative song format after the file workflow works.
For an intro/loop pair, use the complete file-backed registration pattern in that guide. For a theme that changes with surfing or story state, read Events and Hooks, then the music.select entry in Hook Reference. A conditional hook also needs every song it returns to be registered; it is not part of this lesson's checkpoint.
Return to the tutorial index to choose the next lesson.
Start here
Playing
Tutorials
- Choose a tutorial
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Creative guides
Concepts
Recipes and reference
Author and developer tools
Home · Start Playing · Glossary · Troubleshooting · Repository · Community
Game data is imported locally from a supported ROM supplied by the player. Shared mods contain original work or transform recipes, never extracted game content. Check each guide's target game before using its examples.