Integrating fortISSimO into a RGBDS project
Using fortISSimO, like many libraries, has three parts to it.
Global init
fortISSimO has a few variables that must be initialised before some routines are called. Forgetting to do so should result in uninitialised RAM being read (which your emulator is probably configured to warn you of). The ideal time to initialise those is right after booting (example).
hUGE_MutedChannelsmust have been written to (usually to 0, but see the chapter about sound effects) beforehUGE_TickSoundis ever called.
Selecting a track
Here comes hUGE_SelectSong!
This function simply needs to be called with the song’s label in de (example).
This function’s relationship with the APU is as follows:
-
This function does not touch
NR52, so you must turn the APU on yourself beforehand (typically as part of the global init above, see this example). -
This function does not touch
NR51orNR50either; if your songs make use of panning, they should include8xxand/or5xxeffects on their first row to reset those registers.Keep in mind that
8xxand5xxare global, and thus affect sound effects as well! -
This function mutes every channel that is “owned” by the driver; if you do not want this (for example, to join two tracks seamlessly), set
hUGE_MutedChannelsto e.g. $0F before callinghUGE_SelectSong, and restore it afterwards.
Additionally, hUGE_TickSound must not run in the middle of this function!
This can happen if it is called from an interrupt handler, notably.
The recommended fix is to “guard” calls to hUGE_TickSound, like this:
xor a
ldh [hMusicReady], a
ld de, BossFightMusic
call hUGE_SelectSong
ld a, 1
ldh [hMusicReady], a
; In the interrupt handler:
ldh a, [hIsMusicReady]
and a
call nz, hUGE_TickSound
Another possibility is to disable interrupt handlers (usually with di and ei) while hUGE_SelectSong is running; this can have side effects that affect your game, and is therefore not recommended.
Playback
hUGE_TickSound is the function whose use requires the most attention.
Calling this function steps playback forward by 1 tick… which is the most fundamental unit of time in hUGETracker!
A given track expects this function to be called on a specific schedule, otherwise it will sound wrong. Imagine playing a MP3 file at 1.5× speed, for example—that’s not quite it, but close.
The schedule is simple:
-
If “Enable timer-based tempo” was not selected in hUGETracker, then
hUGE_TickSoundmust be called once per frame. This is most often done from an interrupt handler (preferably STAT to save VBlank time, but VBlank is fine too), but can also be done in the main loop.You can pass the
--vblankoption to teNOR to check that the song is properly formatted for this schedule. -
If “Enable timer-based tempo” was selected in hUGETracker, then
hUGE_TickSoundmust be called at a fixed rate. This rate can be obtained by settingTACto 4 (4096 Hz) andTMAto the value in the “Tempo (timer divider)” field, or any equivalent method.You can pass the
--timeroption to teNOR to check that the song is properly formatted for this schedule.
Timer-based tempo can have annoying side effects to the rest of the game’s programming, so VBlank-based tempo is recommended.