^ The ROM in action.
So, what about the mystery ROM? If you try to run the ROM in an emulator, it will do nothing. If you try to run the ROM on actual hardware, preferably a DMG, you might hear the faint sound of the first couple of bars of the Super Mario Bros overworld theme if you hold up the speaker to your ear. But what is the relevance of this?
Let’s step back a moment. If you use LSDj, you might have noticed that LSDj can sometimes make a weird noise. This has to do with the power save functionality. LSDj used to have a power save setting, which increased battery life. It’s well known that turning this feature on would create a certain amount of noise in the audio output, which might not be desirable for a music application. This setting used to have three options, off, auto and full. Off would never save power (“audio quality über alles”), auto would only save power when not playing music (“I often leave my Gameboy powered on and don’t want to drain my batteries”) while full would always use the power saving techniques (“I’m on a long car trip and don’t want to risk draining the batteries”).
Later versions don’t have this setting, and instead always have it set to auto, with no user setting. The code is however slightly modified so that the noise is practically only generated when you touch any of the buttons, and not when you leave the Gameboy idle.
What is the source of this noise? Let’s look at how the power save function works. The Gameboy CPU has a special “halt” instruction. This instruction causes the CPU to partially power down until the it receives an interrupt. A common interrupt is the VBlank interrupt, or screen refresh interrupt which happens about 60 times per second. When that code is finished running, the CPU goes back to sleep. However, because the CPU is being shut down, it draws less current for a period of time, until the CPU is kicked back alive by the interrupt and starts drawing more current again.
This periodical change in power consumption causes the power supply voltage (nominally +5V) to fluctuate slightly. This, in turn creates the sickly noises in LSDj. However, if you can control the period the CPU is sleeping or alive, you can make the interference resemble useful sounds. And this is exactly what this ROM does. It uses the timer interrupt to create the notes. (The timer interrupt can be set to generate an interrupt periodically at arbitrary intervals.) The code then alternates between sleeping and sitting in a wait loop, which causes the voltage rail to fluctuate up and down. Since the signal is transferred through the voltage rail and not the regular audio path, the volume dial will actually have no effect on the volume of the sound! Try adjusting the volume while running this rom. (This works when using the internal speaker or headphone jack, but not a prosound.)
The ROM also contains a lookup table with timer values corresponding to different notes, and a very simple sequencer using the VBlank interrupt to advance the song. The frequency table is situated at address $0300 (hex). The sequence is situated at $0200 and has a two byte command format. The first byte is the note value and the second byte is the note duration, in 1/60 of a second. The note value can be 0-48, at semitone intervals. (4 octaves starting from 128 Hz, with very low accuracy in the higher octaves.) The note value has two special value, $fe meaning pause for x/60 seconds, and $ff, meaning restart sequence. Not that I think this ROM would be very useful as a music sequencer, so you probably shouldn’t bother trying to modify it.
To answer a specific question about the code… While the timer interrupt handler appears to be doing nothing, (just resumes execution) it actually has a function. The main loop works by either sleeping or busy-waiting until a timer interrupt happens, and then enables interrupts. By allowing the interrupt handler to be executed, the interrupt request bit in the IF register ($ff0f) is cleared. I could have done this manually from the main loop, but this is how I chose to do it.