Home

Awesome

SoundSystem Audio Driver

SoundSystem Example

History

The GameBoy Tracker audio system (aka The Paragon5 player) was created in 1999 by Stephane Hockenhull and used in several commercial GameBoy titles, including Project S-11, Shantae, ESPN National Hockey Night, and Who Wants to Be A Millionaire.

Stephane graciously released the export-capable tracker and replay routines to the public in July 2014. The assembler files that it exports were compliant with a circa 2014 version of RGBDS.

RGBDS has since seen many upgrades and improvements that make those tracker-exported assembler files unusable (without modification, see Integration below) with today's RGBDS. The player code itself is showing its age, making it also quite difficult to integrate.

Thus, the SoundSystem audio driver was created.

SoundSystem Introduction

The SoundSystem driver is a modernization of the GameBoy Tracker replayer that Stephane wrote. It was rewritten from the ground-up, reusing the core structure and effects routines where possible, and enhanced to make integration into your project very simple. It's perfect for games or demos or whatever else needs audio.

You can put the SoundSystem driver code in any bank you wish, and it includes support for very large ROMs (more than 256 banks). Instead of one large section of a bank for the code, the SoundSystem driver code is composed of many small sections so it can fit around your more critical code and locations in a bank. It can play both music and sound effects at the same time, and is very fast, even on DMG!

Other peep-hole optimizations were made and it is free of exceptions. It is as fast (if not slightly faster in some cases) as the original replayer and consumes about the same amount of ROM and WRAM space: 3329 bytes max* of ROM, and 91- bytes max* of WRAM (* depending on the options you assemble with. See Integration below for more details.)

Materials

Included in this repository is the source code to the driver, and an example ROM with its source code you can use as an integration reference. The example has several songs as well as sound effects and it shows some of the other features like synchronization and VU meters.

Composing (GameBoy Tracker)

The tracker program is part of Stephane's release materials that you can download from his wiki page. There are download links for various systems and it includes example songs that you can load and change and re-export along with help files. The same song files that are included are the ones that are included in the SoundSystem repository and example ROM.

Integration

Song/Instrument Data

As was previously mentioned, the source files that GameBoy Tracker exports are for an old version of RGBDS, so they will need modification before they can assemble successfully.

For each song (or set of sound effects) that you export, two files will be created: a .z80 source code file that contains the data, and a .inc file that has declarations for exported symbols. You won't need the .inc file so you can delete it.

You will need to make some changes in the .z80 file. First, you need to delete the line that INCLUDEs the .inc file you discarded. Next, change all DATA SECTION types to ROMX. Finally, if the .z80 file is for music, find the label for the order table data (this starts with Music_) and add a second : to make the symbol public. Do the same for the SFX (instrument) table label; this starts with Inst_. There is only one label in a sound effects .z80 file that you need to add a second : to; it starts with SFX_.

SoundSystem Source

There are four source files provided in the SoundSystem driver:


SoundSystem.asm

This is the entire source code to the SoundSystem driver; it is self-contained and doesn't require any external (non SoundSystem) INCLUDE files. Every routine and code block is contained in its own SECTION but the actual routines that get assembled is determined by the contents of SoundSystem.def. For example, if you only need to play music (say, for a demo), you don't have to include the code that plays sound effects. Similarly, if your project doesn't need the VU meters feature, you can disable that code to make the ROM (and WRAM) footprint smaller.

After successful assembly of this file, it will display the configuration it was built with (as defined by SoundSystem.def). For example:

SoundSystem Configuration:
     GBC Only: no
    Large ROM: no
    Code Bank: $0
    WRAM Bank: $0
          SFX: ENABLED
    VU Meters: ENABLED

SoundSystem.def

This is an INCLUDE file that controls the behavior of the SoundSystem driver. By including/excluding certain values described below, you can include/exclude features and control the behavior. These are build-time settings, so you can turn code on and off depending on your specifications.

SOUNDSYSTEM_GBC_COMPATIBLE

By default, SoundSystem assumes it is part of a DMG-only ROM. If the value at $143 in your ROM is set to DMG/GBC ($80) or GBC ($C0), you should set SOUNDSYSTEM_GBC_COMPATIBLE to 1.

Notes:

SOUNDSYSTEM_LARGE_ROM

By default, SoundSystem assumes it is part of a 'small' ROM. That is, 4MBytes (256 banks) or smaller. If the value at $148 is set to CART_ROM_8192K ($08), you should set SOUNDSYSTEM_LARGE_ROM to 1 to allow you to place your code and/or audio data into banks >=256.

Notes:

SOUNDSYSTEM_ROM_BANKING

By default, SoundSystem will automatically store and change ROM banks. However, if your ROM does not use banking (i.e. it is a 32KByte ROM), set SOUNDSYSTEM_ROM_BANKING to 0, and the current ROM bank will be left alone.

Notes:

SOUNDSYSTEM_CODE_BANK

By default, SoundSystem will place its code and data in ROM bank 0. If you want to place it in a different bank, set SOUNDSYSTEM_CODE_BANK to the bank id.

Notes:

SOUNDSYSTEM_WRAM_BANK

By default, SoundSystem will place its WRAM variables in WRAM bank 0. If you want to place it in a different bank, set SOUNDSYSTEM_WRAM_BANK to the bank id.

Notes:

SOUNDSYSTEM_ENABLE_SFX

By default, SoundSystem assumes it is part of a game (instead of a demo or some other music-only project.) Therefore, sound effects are enabled by default. If you only need to play music, setting SOUNDSYSTEM_ENABLE_SFX to 0 will remove that code and not try to process any sound effects.

Notes:

SOUNDSYSTEM_ENABLE_VUM

SoundSystem can provide data that can drive a VU-meter type display. This is disabled by default, but access to that data is provided by setting SOUNDSYSTEM_ENABLE_VUM to 1.

If enabled, the data (value $0-$F) is in 4 1-byte variables, one per channel:

They are contiguous in memory so you can access them as an array if needed.

Notes:


SoundSystem.inc

This is essentially documentation on the routines included in the driver and any supporting EQUates. (The text from The API section below came from this file.)


SoundSystemNotes.inc

This is an optional INCLUDE file provided as a convenience. It contains EQUates for note values that you can pass into SFX_Play. You do not need to include this file in your project if you don't need it.

The API

As an optimization, the routines in the SoundSystem driver do not preserve the registers it uses. It is up to you to preserve any register(s) you want to keep before any call to SoundSystem. Any/all registers that each routine uses is listed below in the routine descriptions.

Also, depending on how you have your SoundSystem.def set up, it's likely that the ROM and/or WRAM bank will change after each SoundSystem call. It is up to you to restore or change banks as appropriate.

Main Driver Functions

SoundSystem_Init

This prepares SoundSystem for use. It must be called before any other SoundSystem functions can be called.

Arguments: None

Example:

    call SoundSystem_Init

SoundSystem_Process

This is the 'heartbeat' of the driver so it should be called every frame. The exact time (in a VBlank or during a frame) isn't important; provided it is called at a regular interval.

CPU usage is dependent on the audio SoundSystem is processing. Each effect has a cost and so the CPU time is not fixed.

Notes:

Arguments: None

Example:

    ; preserve any registers, if applicable
    call SoundSystem_Process
    ; switch ROM bank, if applicable
    ; switch WRAM bank, if applicable

Song (Music) Features

Music_PrepareInst

In order for music to be playable with Music_Play (see below), it needs to be 'prepared' first. This routine tells SoundSystem where the instrument table resides, which can be in a different location where the actual music order table (pattern data) resides.

Notes:

Arguments:

Example:

    ld   bc,BANK(Inst_s11space)
    ld   de,Inst_s11space
    call Music_PrepareInst

Music_Play

This is the trigger to start music actually playing (and processed by SoundSystem_Process). The order table data can reside in a different location to the instrument data. SoundSystem will handle bank swapping as and when it needs to.

Notes:

Arguments:

Example:

    ld   bc,BANK(Music_s11space)
    ld   de,Music_s11space
    call Music_Play

Music_Pause

This pauses music playback. After the music is paused, it is safe to call SoundSystem_Process and sound effects can still be triggered. Call Music_Resume (see below) to continue the music playback.

Notes:

Arguments: None

Example:

    call Music_Pause

Music_Resume

This resumes music playback after Music_Pause (see above) has called.

Notes:

Arguments: None

Example:

    call Music_Resume

Sound Effect (SFX) Features

SFX_Prepare

In order for one-shot sound effects (SFX) to be playable with SFX_Play (see below), they need to be 'prepared' first. This routine tells SoundSystem where the sound effects table resides, which can be in a different location where the music data resides.

Notes:

Arguments:

Example:

    ld   bc,BANK(SFX_Table)
    ld   de,SFX_Table
    call SFX_Prepare

SFX_Play

This is the trigger to start a one-shot sound effect actually playing (and processed by SoundSystem_Process).

Notes:

Arguments:

Example:

    ld   b,COOL_SFX_1
    ld   c,C_4
   ;ld   bc,(COOL_SFX_1<<8)|C_4    ; or this way as an optimization
    call SFX_Play

SFX_Stop

This immediately terminates all one-shot sound effects from playing.

Notes:

Arguments: None

Example:

    call SFX_Stop

SFX_LockChannel3/SFX_UnlockChannel3

This pair of routines affect the wave channel (channel 3) of the GameBoy. Locking the channel will prevent music and other sound effects from using that channel until it is unlocked again.

Notes:

Arguments: None

Example:

    call SFX_LockChannel3
    ...
    call SFX_UnlockChannel3

Miscellaneous Features

Playback State

You can check the playback state by inspecting wMusicPlayState. EQUates are provided for possible values: either stopped or playing.

MUSIC_STATE_STOPPED EQU 0
MUSIC_STATE_PLAYING EQU 1

Synchronization

The tracker has a mechanism that provides a way to synchronize the code with the music via the Zxx Flag Command. This sends a value ($00-$FF) to the code to be processed however applicable (or ignored).

wMusicSyncData

Notes:

VU Meters

SoundSystem can provide data that can drive a VU-meter type display. This is disabled by default, but access to that data is provided by setting SOUNDSYSTEM_ENABLE_VUM in SoundSystem.def to 1.

If enabled, the data (value $0-$F) is in 4 1-byte variables, one per channel:

They are contiguous in memory so you can access them as an array if needed.

Notes:

Identity

There are two symbols that can be used for attribution: SoundSystem_Version and SoundSystem_Author.

Notes:


Important Notes

This repository was created and is maintained by GBSS maintainers with Stephane's approval. As such, if you have questions or comments about SoundSystem, you can create an issue here in the repository (feel free to create a PR if you're so inclined) and direct them to me.

Any questions specifically about GameBoy Tracker (including the materials found there) or licensing questions, you must direct them to Stephane.

SoundSystem is a Derivative Work (which is why you will see Stephane's name in your ROM, not mine) that is released under the MIT License (see LICENSE for more details) but questions regarding licensing for commercial projects need to be directed to Stephane.