hUGETracker logo

This is the manual to hUGETracker. I wrote this program because there wasn’t a music editing tool for the Game Boy which fulfilled the following requirements:

  • Has a tracker interface
  • Produces small output
  • Is usable for homebrew titles
  • Is open-source

But now there is!

I’d like to acknowledge:

  1. Eldred “ISSOtm” Habert, who helped me navigate the Game Boy’s peculiarities, and for writing an alternative sound driver for the tracker;
  2. Tony “Toxa” Pavlov, who helped work on the sound driver and did super valuable work on integration with GBDK-2020;
  3. Coffee “Valen” Bat, for a crazy amount of testing, documentation, code, and support for new users;
  4. Michael “Calindro” Stegmaier for Emulicious, a super-accurate emulator that is invaluable for debugging
  5. Evelyn “Eevee” Woods, whose article on the Game Boy sound system was valuable in writing the music driver;
  6. B00daW, for testing and debugging support on Linux;
  7. Lior “LIJI32” Halphon for SameBoy, a super-accurate emulator which I used for debugging, and copied the LFSR code from;
  8. Christian Hackbart for creating UGE, which serves as hUGETracker’s emulation core;
  9. Rusty Wagner for writing the sound code which was adapted for UGE;
  10. The team who created RGBDS, the assembler used for building ROMs from songs;
  11. The GBDev community, the GBDK-2020 community, and the GBStudio community.

I hope you enjoy composing in hUGETracker, and if you make any cool songs, I’d love to hear from you and potentially include them as demo tunes that come with the tracker.

Join the hUGETracker discord and get in touch!

—Nick “SuperDisk” Faro

Contact us

Glossary

TermDefinition
CellA note, an instrument, and an effect. This is a single row in a pattern.
ChannelOne of the Game Boy’s 4 voices for producing sound. There are 2 pulse channels, one wave channel, and one noise channel.
DutyThe parameter that determines the waveform of a pulse channel. A pulse channel has two states (on or off), and the duty cycle specifies what percentage of the time it’s on. A pulse channel with 50% duty would emit a square wave.
EffectConsists of an effect code and effect parameter. Used for a variety of reasons, including changing the way a specific note sounds, changing global settings such as master volume, affecting song tempo, or calling your own custom code.
Effect codeA hexadecimal digit which specifies which effect to use.
Effect parameterTwo hexadecimal digits which tweak the effect’s behavior.
InstrumentA bunch of parameters which change the way a channel produces sound. Each cell must include an instrument number.
Octave offsetWhen entering note values into the tracker grid, the value of the note is increased by 12 × octave offset, to allow for more natural entry of higher notes.
OrderA row of four pattern indices. An order is how you arrange patterns into a structured song.
Order tableA list of orders, representing the structure of the song.
PatternA list of 64 cells, used to represent 2 measures of music. This is the basic building block of your song.
RenderExporting a song as a .wav or .mp3 file, so anybody can listen to them without hUGETracker or an emulator installed.
RoutineA custom effect written in Game Boy assembly. An advanced featuer that would typically be used when integrating hUGETracker into a homebrew game, or perhaps for making custom effects.
SongThe whole track, which includes patterns, orders, instruments, waves, and routines.
SweepA change of pitch over time. The Game Boy sound hardware provides the ability for the first pulse channel to perform a sweep as specified by some instrument parameters.
TickEvery time the sound driver update function is called, it advances the song by one tick. This is usually done at around 60 Hz.
TempoThe tempo of a song specifies how many ticks have to elapse before switching to the next row. The greater it is, the slower the song is.
WaveA waveform which changes the timbre of the wave channel when selected. You can draw these in the wave tab. They must be associated to an instrument in the instruments tab.

Interface

The hUGETracker interface is styled similarly to conventional trackers such as ModPlug Tracker / OpenMPT or ProTracker. If you’re comfortable composing in a tracker interface, then you’ll feel right at home.

Screenshot of the hUGETracker main interface

Legend:

  1. Tracker grid
  2. Order editor
  3. Song components
  4. Toolbar

Tracker grid

Screenshot of the tracker grid

The tracker grid displays four patterns together. This represents one row in the order table, and is the component used to compose a song. When a different order is selected in the order table, the patterns in the tracker grid are updated to reflect their contents.

In a given pattern, there are 64 rows of cells. Each cell is divided into three parts: the note, the instrument, and the effect.

A note ranges from C-3 to B-8, and is the pitch of the tone that will play on that cell.

An instrument is a value from 01 to 15, which specifies which instrument parameters will be applied to the playing note.

An effect is the combination of an effect code (the first hexadecimal digit, from 0 to F) and its effect parameter (the last two hexadecimal digits, from 00 to FF). See the effect reference for more details. You can use the Effect Editor to create the effect values for you, if you’re not comfortable entering hexadecimal directly.

The keyboard is used to enter values into the three parts of a cell: the keys Q through \, A through `, and Z through / each represent an octave with which to enter notes. The octave offset can be modified in the toolbar to allow for higher or lower note values.

The numeric keys can enter values into the instrument column.

The numeric keys, as well as keys A through F, enter values into the effect column.

While a song is playing, the highlighted row, representing the row currently being played, moves downwards on the patterns. The tempo of your song (speed at which the highlighted row moves) can be adjusted in the General tab.

The headers of the channels are clickable, and will mute/unmute the playback of a specific channel when playing a song.

Test

The tracker grid also features a right-click menu for opening the effect editor, and performing various editing tasks. These can all be accomplished by using the hotkeys as well.

Screenshot of the order editor

Order editor

The order editor is where you arrange the structure of your song. Since most music tends to be fairly repetitive (a single drum pattern is often enough for the majority of the song, for instance), you can define any number of patterns and arrange them here.

Each column corresponds to a channel in the tracker grid.

Much like the tracker grid, the order editor’s highlighted row moves downward each time a new order is reached. The song loops back to the first order when the last order is finished playing.

An order is a row in this table.

Right-click to open the popup menu, where you can:

  • Insert new row — Inserts a row with all brand-new pattern numbers.
  • Insert empty row — Inserts a row with all zeros in it.
  • Duplicate row — Inserts a row which has the same pattern numbers as the one currently highlighted.
  • Replicate row — Inserts a row with all brand-new pattern numbers, and these new patterns are copies of the highlighted row’s.

Song components

Screenshot of the song components

The components of a hUGETracker song are shown here. Listed are instruments along with their names, waves numbered from 0 to 15, and routines numbered from 0 to 15.

Double-left clicking on any of these will bring you to the tab for editing it.

Toolbar

Screenshot of the toolbar

The toolbar contains various functions that are useful when writing music:

  • Save as… — Saves your song to a file.
  • Start — Plays your song from the very beginning.
  • Cursor — Plays your song starting from the current cursor position. Useful when editing a specific pattern.
  • Stop — Halts playback.
  • Export .GB — Assembles your song into a standalone .gb file, for playback in an emulator or a real Game Boy!
  • Export .GBS — Assembles your song into a standalone .gbs file, for playback in a program such as gbsplay.
  • Render song — Exports your song in either .wav or .mp3 format.
  • Panic — Silences all channels immediately. Useful when something has happened, and a tone is playing that you want to make stop.
  • Octave — Selects the octave offset for the tracker grid.
  • Instrument — Selects the instrument with which to input new notes in the tracker grid. Any new note entered will be accompanied by this instrument number, and a preview note will play with this instrument.
  • Step — Selects the step for the tracker grid. After inputting a new note, the cursor will move down by this many rows; useful for inputting drum tracks or arpeggios.

General

Screenshot of the general tab

The general tab allows specifying the name, artist, and tempo of your song. Name and artist are limited to 255 characters each. Tempo is limited to a value between 0 and 20.

The tempo actually has an inverse relationship to the speed of the song: a higher value results in a slower song.

Instruments

Screenshot of the instruments tab, editing a square instrument Screenshot of the instruments tab, editing a wave instrument Screenshot of the instruments tab, editing a noise instrument

Legend:

  1. Instrument number: This selects which instrument of its type to edit. Ranges from 1 to 15 (inclusive).
  2. Instrument name: This is the name for the instrument. It is shows in the instrument combobox in the toolbar and in the song components.
  3. Instrument type: Selects which “type” of instrument this is. Can be square, for instruments to be played on the pulse channels; wave, for instruments to be played on the wave channel; and noise, for instruments to be played on the noise channel.
  4. Length: When enabled, a playing note will be cut off immediately after a certain amount of time elapses.
  5. Test C-5: Plays a test note for a few seconds, to test what the instrument will sound like.
  6. Import/Export buttons: Used to import or export an instrument’s settings to/from a file.
  7. Sweep time: Selects the “sweep time” for the note to take. The greater the value, the slower the sweep.
  8. Sweep direction: Selects the direction of the sweep the note should take. “Up” portamentos the note up, “Down” portamentos it down.
  9. Sweep size: Selects the magnitude of sweep for the note to take per “tick” as specified by sweep time.
  10. Duty: Selects the timbre of note to play. Each setting sounds different, and they are useful when you don’t want both of the duty channels to clash with one another.
  11. Start vol: Selects the starting volume for the envelope. When there’s no change on the envelope, this functions simple as the volume for the note, unless overridden by a volume effect command.
  12. Direction: This specifies which direction for the envelope to go.
  13. Change: This specifies for how long the envelope goes. The higher the value, the more the note will fade in or out.
  14. Wave volume: Specifies at what volume a wave instrument shall play, unless overridden by a volume effect command.
  15. Waveform: Specifies which waveform should play as part of this instrument. See waves.
  16. Shift clock mask: A component of the noise generation algorithm. Tweak it however you want.
  17. Dividing ratio: A component of the noise generation algorithm. Tweak it however you want.
  18. 7-bit counter: When checked, the instrument will sound more like a musical tone rather than noise.
  19. Randomize: Rather than manually tweaking the sliders, you can click this button until you hear something you like. Plays a random configuration of sliders, with a random length, at a random pitch.

Waves

Screenshot of the waves tab

The waves tab allows you to edit waveforms for use by instruments. Use the spinner to select which wave you want to edit, and draw manually with the mouse in the displayed waveform viewer. Waves can also be imported from and exported to files.

Comments

Screenshot of the comments tab

The comments tab allows you to include a comment section with your song, which you can use for acknowledgements, contact information, or anything you want. The comment is limited to 255 characters.

Effect editor

Screenshot of the effect editor

The effect editor is a tool for creating effect values in the tracker grid. This is especially useful for things like panning, or master volume, which operate on a bit level and may be difficult to input manually. Open the editor by double-left clicking in the tracker grid, or with the right click menu.

Effect reference

The hUGETracker effect codes are intentionally similar to ProTracker and FastTracker’s. If you know those, then many of these effects will look familiar to you.

Some things to keep in mind:

  • Effects are only active on the row that they are on; if you want an effect to remain active for several rows, you must re-enter it on each one.

  • Some effects mention “the playing note”, which is the last note played on the channel thus far (possibly in the same row). For example:

    NoteInstrEffect
    C-51
    .047

    …the 047 arpeggio will apply with the C-5 note as its base.

Without further ado, here is the list of effects supported by hUGETracker:

EffectNameDescription
0xyArpeggioWhile this effect is active, the player will cycle on each tick between the playing note, the note + x semitones, and the note + y semitones, in this order. Can be used to create “chords” or a strum effect.
1xxPortamento upSlide the pitch up by xx units every tick. If the row contains a note, then the effect is skipped on the row’s first tick; if the tempo is 1, this means the effect will not do anything at all.
2xxPortamento downSame, but the pitch is slid down instead of up.
3xxTone portamentoInstead of playing the cell’s note, slide the pitch towards that note by xx units every tick. Stops exactly at the note, though.
4xyVibratoEvery x + 1 ticks, switch between the playing note and note + y units. This is similar to arpeggio, except you can control the frequency, and the offset is specified in units rather than semitones.
5xxSet master volumeSet the master volume control of the Game Boy for the left and right speakers. Consider using the effect editor. Note that a volume of 0 is not completely silent!
6xyCall routineCall the user-defined routine number y.
7xxNote delayWait xx ticks before playing the note in this cell. If xx is strictly greater than the tempo, the note will not play at all!
8xxSet panningSet which channels play on which speakers. Consider using the effect editor. Setting a channel to neither left nor right will mute it, but is not recommended1.
9xxChange timbreFor pulse channels (CH1 & 2), this changes the duty cycle2; for the wave channel (CH3), this loads wave xx3; for the noise channel (CH4), this changes the LFSR’s width (caution! 4).
AxyVolume slideSlide the note’s volume5 up by x units, or down by y units (either x or y must be 0). The active note will be retriggered on each tick, which may sound bad if envelope and/or length are present. It is recommended to use instead either instrument envelopes, or the C effect, if possible. This effect is not available on the wave channel (CH3)!
BxxPosition jumpJump to order xx.
CxySet volumeSet the volume of the channel to y, and retrigger the active note. If x is not 0, x will be written to the envelope bits. (To stop the envelope instead, effect A can be used; see below.)
DxxPattern breakJump to the next order, and start on row xx.
ExxNote cutCut the note short after xx ticks; the note won’t be cut if xx is not strictly less than the tempo!
FxxSet tempoSet the number of ticks per row to xx. Can be used in an alternating fashion to create a swing beat.
1

Muting a channel via NR51 may cause an audio pop, and also tends not to play nice with sound effect engines that don’t override NR51. Further, since NR51 is a global effect, it’s still applied even if the channel is “muted”.

2

xx is written directly to the channel’s length register; if the active instrument has “length” enabled, the length will be reloaded immediately.

3

Due to hardware limitations, changing the wave requires restarting the active note.

4

Switching the LFSR from “long mode” to “short mode” at a certain time “locks up” the noise channel, silencing it until it’s retriggered. This should happen consistently for an affected song, and may not appear in the tracker.

5

Due to hardware limitations, A bases itself off of the instrument’s initial volume, and doesn’t take its envelope, if any, into account.

Tips and tricks

  • A stops the current instrument’s envelope if one is active. A00 is probably not desirable (see footnote above5), so consider using it in a subpattern, so that it is only active for a single tick.
  • Using C causes a click, so prefer baking the volume into the instrument when possible.
  • Vibrato using repeated 2xx and 1xx effects can give better results and more intricate/detailed vibrato than 4xy, especially in subpatterns.
  • Alternated Fxx effects can help with reaching decimal speeds. For example, alternating between F04 and F03 yields a speed of 3.5; cycling through F01, F01, F02 and F01 yields a speed of 1.25; and so on.
  • Notes without an instrument on their row can help with reducing noise, as the note isn’t retriggered. Of course, this only works if you weren’t planning to change the instrument.

Hotkeys

The keyboard interface to hUGETracker is intentionally designed to be similar to ModPlug’s. If you are used to it, then most of these keybindings will look familiar.

HotkeyActionDescription
Ctrl+CCopyCopies the selected pattern data into the clipboard.
Ctrl+XCutCopies the selected pattern data into the clipboard, then erases the selected pattern data.
Ctrl+VPastePastes any pattern data stored in the clipboard.
Shift+VFlood pasteRepeatedly pastes stored pattern data until reaching the bottom of the pattern. Useful for repeating beats/phrases/swing tempos.
Ctrl+QSemitone upTransposes the selected notes one semitone up.
Ctrl+ASemitone downTransposes the selected notes one semitone down.
Ctrl+Shift+QOctave upTransposes the selected notes one octave up.
Ctrl+Shift+AOctave downTransposes the selected notes one octave down.
Ctrl+LSelect channelSelects the entire pattern that the cursor is located in.
DeleteEraseErases the selected note data.
Ctrl+ZUndoUndoes the previous action.
Ctrl+YRedoRedoes that action last undone.

Subpatterns

Subpatterns are one of hUGETracker’s most powerful features. They are like mini-tracker grids attached to instruments, which allow you to use effects on very precise ticks. They fulfill the same role as instrument macros in FamiTracker.

What are subpatterns useful for?

  • Percussion! (Subpatterns replace noise macros)
  • Cooler arpeggios than effect 0!
  • Nicer vibratos than effect 4!
  • “Pluck” sounds! (Start one octave up, then go back to base)
  • Serves as an extra FX channel in a pinch!
  • Changing timbre really quickly! (Use effect 9)
  • And much more!

Screenshot of a subpattern with offsets and jumps Screenshot of a subpattern with effects

Rows are composed of three columns, similiar but not identical to the tracker grid’s:

  • an offset,
  • an optional jump to a specific row,
  • and an effect.

The offset is a positive number of semitones that is applied to the base note.

Subpatterns automatically loop back to the beginning, or can be made to jump backwards earlier via the jump column. If you want to halt a subpattern in place and have it not loop at all, specify a jump command that jumps to itself.

Interaction with the “regular” tracker grid

Subpatterns take precedence over the “regular” tracker grid. That is, if there’s a row on the tracker grid like so:

C-5 05 101

And the first row of instrument 05’s subpattern is:

+02 ... ...

Then the +02 offset in the subpattern will override the 1xx portamento up effect.

Effects

Effects in subpatterns work just like in the regular tracker grid (reference), except for two things:

  • each effect only lasts for a single tick (just like the rows);
  • not all effects can be used in subpatterns:
EffectNameUsable?Notes
0xyArpeggioYesTechnically you can use this, but 1) you would have to use it on many rows consecutively, and 2) you can just use the offset column instead.
1xxPortamento upYesThe “units” are finer than semitones, so this can be used to increase granularity
2xxPortamento downYesSame as above.
3xxTone portamentoNoThere is no “target note” in the first place.
4xyVibratoYesThis can give finer control than the offset column, but you will have to use this effect on many consecutive rows, and the portamento effects may work better in the first place.
5xxSet master volumeYes
6xyCall routineYes
7xxNote delayNoThere is no note in the first place.
8xxSet panningYes
9xxChange timbreYes
AxyVolume slideYesC may be more appropriate, since this will only be active for a single tick.
BxxPosition jumpNoUse the jump column instead.
CxySet volumeYes
DxxPattern breakNoUse the jump column instead.
ExxNote cutNoUse C00 instead.
FxxSet tempoYes…but why would you do this?

Routines

Routines allow you to implement your own effects. The feature is currently not documented here, and is subject to change soon. If you’re really interested, check out the hUGEDriver/driverLite.z80 file.

hUGETracker .UGE v5/v6 format spec

Data types

NameByte lengthDescription
uint81Also known as char, ranges from 0 to 255.
uint324Also known as word, ranges from 0 to 4,294,967,295.
int81Ranges from -127 to 127.
bool1If not-zero, then True.
shortstring256Consists of a byte defining the readable length and then 255 characters.
string-Consists of a uint32 defining the number of characters, and then a stream of characters, with 0x00 being the terminator value.

All types are little endian unless noted otherwise.

  • uint32 Version number
  • shortstring Song name
  • shortstring Song artist
  • shortstring Song comment

Duty Instruments

  • Repeat 15 times:
    • uint32 Type (0)
    • shortstring Instrument name
    • uint32 Length
    • bool Length enabled
    • uint8 Initial volume
    • uint32 Volume sweep direction (0 = Increase, 1 = Decrease)
    • uint8 Volume sweep change
    • uint32 Frequency sweep time
    • uint32 Sweep enabled (1 = Enabled, 0 = Disabled)
    • uint32 Frequency sweep shift
    • uint8 Duty cycle
    • uint32 Unused
    • uint32 Unused
    • If Version number < 6:
      • uint32 Unused
    • uint32 Unused
    • If Version number < 6:
      • uint32 Unused
    • Else:
      • bool Subpattern enabled
        • Repeat 64 times:
          • uint32 Row note (0 through 72, 90 if not used)
          • uint32 Unused
          • uint32 Jump command value (0 if empty)
          • uint32 Effect code
          • uint8 Effect parameter
    • If Version number >= 4 and Version number < 6:
      • Repeat 6 times:
        • int8 unused

Wave Instruments

  • Repeat 15 times:
    • uint32 Type (1)
    • shortstring Instrument name
    • uint32 Length
    • bool Length enabled
    • uint8 Unused
    • uint32 Unused
    • uint8 Unused
    • uint32 Unused
    • uint32 Unused
    • uint32 Unused
    • uint8 Unused
    • uint32 Volume
    • uint32 Wave index
    • If Version number < 6:
      • uint32 Unused
    • uint32 Unused
    • If Version number < 6:
      • uint32 Unused
    • Else:
      • bool Subpattern enabled
        • Repeat 64 times:
          • uint32 Row note (0 through 72, 90 if not used)
          • uint32 Unused
          • uint32 Jump command value (0 if empty)
          • uint32 Effect code
          • uint8 Effect parameter
    • If Version number >= 4 and Version number < 6:
      • Repeat 6 times:
        • int8 Unused

Noise Instruments

  • Repeat 15 times:
    • uint32 Type (2)
    • shortstring Instrument name
    • uint32 Length
    • bool Length enabled
    • uint8 Initial volume
    • uint32 Volume sweep direction (0 = Increase, 1 = Decrease)
    • uint8 Volume sweep change
    • uint32 Unused
    • uint32 Unused
    • uint32 Unused
    • uint8 Unused
    • uint32 Unused
    • uint32 Unused
    • If Version number < 6:
      • uint32 Unused
    • uint32 Noise mode (0 = 15 bit, 1 = 7 bit)
    • If Version number < 6:
      • uint32 Unused
    • Else:
      • bool Subpattern enabled
        • Repeat 64 times:
          • uint32 Row note (0 through 72, 90 if not used)
          • uint32 Unused
          • uint32 Jump command value (0 if empty)
          • uint32 Effect code
          • uint8 Effect parameter
    • If Version number >= 4 and Version number < 6:
      • Repeat 6 times:
        • int8 Noise macro data

Wavetable data

  • Repeat 16 times:
    • Repeat 32 times:
      • uint8 Wavetable nibble data
    • If Version Number < 3:
      • uint8 Off by one filler

Song Patterns

  • uint32 Initial ticks per row
  • If Version number >= 6:
    • bool Timer based tempo enabled
    • uint32 Timer based tempo devider
  • uint32 Number of song patterns
  • Repeat Number of song patterns times:
    • uint32 Pattern index
    • Repeat 64 times:
      • uint32 Row note (0 through 72, 90 if not used)
      • uint32 Instrument value (0 if not used)
      • If Version number >= 6:
        • uint32 Unused
      • uint32 Effect code
      • uint8 Effect parameter

Song Orders

  • Repeat 4 times (Duty 1, Duty 2, Wave, Noise):
    • uint32 Order length + 1 (Off by one bug)
    • Repeat Order length times:
      • uint32 Order index
    • uint32 Off by one bug filler (0)

Routines

  • Repeat 16 times:
    • string Routine code data

Miscellaneous

Here are some random things about hUGETracker.

The clipboard

The clipboard format for hUGETracker is compatible with ModPlug Tracker / OpenMPT! This means that you can convert your existing .mod, .xm, .s3m, or .it chiptunes into Game Boy tunes very quickly by just copying and pasting your patterns into hUGETracker. Note that the effects are not converted when pasted, so you’ll need to manually adjust the effects to work in hT.

Screenshot of the clipboard format of hUGETracker and ModPlug

Screenshot of the same clipboards, pasted into hUGETracker and ModPlug

Command Line Options

hUGETracker supports loading a module passed as the first command line argument. Additionally, data directories can be configured using the --conf_dir, --cache_dir and --runtime_dir options. This allows running hUGETracker from a read-only directory, or packaging hUGETracker for Linux distributions.

OptionInformation
--conf_dirWhere user configuration is stored (settings, keymaps, color schemes).
--cache_dirWhere intermediate files generated during song assembly are stored.
--runtime_dirWhere necessary files that normally ship with hUGETracker are stored. This includes hUGEDriver, halt.gb, etc.

What is hUGEDriver?

hUGEDriver is a driver for hUGETracker. What does that mean?

Well, think about an MP3 file: a program like VLC is required to play those back. Similarly, hUGETracker “only” generates music data, and something has to interpret it to actually produce sound.

This is also why hUGEDriver is also called a “player” for hUGETracker, though this is slightly inexact, because hUGEDriver is not a complete playback solution: it’s meant to integrate with your code, that will decide what music must be played, when, and how. For more information about that, please read the next chapter.

Notes

Make sure to always use compatible versions of hUGETracker and hUGEDriver together!! For example, you cannot use hUGETracker 1.0b10 with hUGEDriver 1.0b9, as the data format is different between those two versions.

hUGEDriver is the reference driver, meaning that it will always be kept up to date. Other implementations (such as fortISSimO) are available, but they are not officially supported.

Under the hood, hUGETracker plays your songs by emulating a Game Boy running hUGEDriver. Doing it this way instead of interpreting the music data directly helps avoiding any discrepancies between playback in the tracker and on the console. If you find any, it’s probably a bug, please tell us!

Integration

Integrating hUGEDriver into your project depends on what you are using.

First, get the release of hUGEDriver that matches your version of hUGETracker.

RGBDS (assembly)

Import hUGEDriver.asm and hUGE.inc (in the include directory) into your project (songs need the latter as well). You will additionally need hardware.inc 4.2 or later, if you don’t already.

Then, simply compile hUGEDriver.asm with the rest of your code, and you’re done!

GBDK (C)

hUGEDriver releases contain a pre-compiled .lib for use with GBDK-2020. Link it while compiling, include hUGEDriver.h, and you’re done:

lcc ... -Wl-lhUGEDriver.lib

If you want to compile the driver yourself, a few extra steps are necessary.

  1. You will need RGBDS, and Python
  2. Assemble hUGEDriver: rgbasm -o hUGEDriver.obj hUGEDriver.asm
  3. Convert the object file: python tools\rgb2sdas.py -o hUGEDriver.o hUGEDriver.obj
  4. Import hUGEDriver.h into your project
  5. Simply link hUGEDriver.o with the rest of your code, and you’re done!

Usage

There are two parts to using hUGEDriver: initializing a song, and playing a song.

Initialization

You begin playing a song by passing a pointer to it to the hUGE_init function. How can you get such a pointer, though? Simple! The “song descriptor” that you choose when exporting your song names a label (assembly) / variable (C) that points to the song! So if your song descriptor was, say, ryukenden:

AssemblyC
ld hl, ryukenden
call hUGE_init
hUGE_init(ryukenden);

Playing

The function hUGE_dosound plays a single tick of the current song when called.

First and foremost, how often should that function be called? That actually depends on what the song expects!

Screenshot of the tempo settings

If the song does not use “timer playback”, then hUGE_dosound must be called once per frame. This is usually done either by calling it from your game’s main loop, or by calling it from your VBlank interrupt handler. However, if the song does use timer playback, then you must set the timer registers appropriately (TODO), and call hUGE_dosound from the timer interrupt handler.

Using an interrupt handler exposes you to two additional constraints:

  • hUGE_dosound must not run in the middle of hUGE_init.
  • hUGE_dosound must not be called before the first call ever to hUGE_init.

Preferably, create a variable that you set to 0 on boot before calling hUGE_init, and to 1 after hUGE_init returns; in the interrupt handler, skip calling hUGE_dosound if the variable isn’t 0. An alternative is to disable interrupts (ASM: di+ei, GBDK: __critical) while you call hUGE_init.

Sound effects

hUGEDriver itself does not provide sound effects, but is compatible with existing sound effect solutions. Both music and sound effects need to contend for the Game Boy’s four sound channels, so a little cooperation is required.

The general outline of how to play sound effects and music is as follows:

  1. Tell hUGEDriver to “release” a channel; that is, hUGEDriver refrains from touching it at all, which leaves it free for other code to use (say, an SFX engine, or a sample player).
  2. Use your SFX engine to play a sound effect on that channel
  3. After the sound effect is complete, tell hUGEDriver to use the channel again, so music will resume playing on that channel

“Releasing” a channel is also known as “muting.”

How-to

RGBDS (assembly)

Call hUGE_mute_channel with b containing the channel’s ID minus one (so between 0 and 3 inclusive), and c being 0 to release the channel, or 1 to unmute it.

GBDK (C)

Call hUGE_mute_channel; see hUGEDriver.h for the corresponding arguments.

Notes

  • IMPORTANT precaution for CH3: if you release this channel and modify wave RAM, you must inform hUGEDriver, by writing hUGE_NO_WAVE to hUGE_current_wave. This will tell hUGEDriver to reload wave RAM when the channel is un-released; otherwise, you may get the wrong waveform when the music resumes.
  • “Global” effects (5, 8, B, D, and F) are still processed, even if the channel they are attached to is released. Importantly, this means hUGEDriver will write to NR50 (5) and NR51 (8).

SFX Engines

These projects aren’t part of hUGETracker, but they’re known solutions that work well with it:

  1. VGM2GBSFX - Can use VGM files as sound effects. Since hUGETracker can export to .vgm, you can make your sound effects in hUGETracker!
  2. CBT-FX - Sound effect engine compatible with FX Hammer
  3. Libbet’s SFX Engine - Simple engine for assembly projects