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).

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 (typically as part of the global init above, see this example).

  • This function does not touch NR51 or NR50 either; if your songs make use of panning, they should include 8xx and/or 5xx effects on their first row to reset those registers.

    Keep in mind that 8xx and 5xx are 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_MutedChannels to e.g. $0F before calling hUGE_SelectSong.

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_TickSound must 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.
  • If “Enable timer-based tempo” was selected in hUGETracker, then hUGE_TickSound must be called at a fixed rate. This rate can be obtained by setting TAC to 4 (4096 Hz) and TMA to the value in the “Tempo (timer divider)” field, or any equivalent method.

Timer-based tempo can have annoying side effects to the rest of the game’s programming, so VBlank-based tempo is recommended.