defMON wiki — using a defMON tune in your own program
The defmon wiki's developer pages: how to link a packed defMON tune into an assembly project, the init/play/update entry points (including the multispeed split), and the self-modifying global-volume location. "The interface is more or less the same as in 90% of all other sid tunes out there, at least if you are going to play a single speed tune."
Key claims#
Linking and init#
- Place the packed tune at
$1000:* = $1000/!incbin "mypackeddefmontune.bin". The first two bytes of a packed tune are the .prg load address ($00,$10) and must be stripped — "An ugly 'trick' is otherwise to include the file at * = $0ffe instead." - Init once before playing:
lda #$00/jsr $1000. The A register selects the start song position (0 = from the beginning). - Gotcha: "the init routine in the defMON player contains a piece of code that detects the SID model (6581 or 8580) in the machine. This routine temporarily disables interrupts, which may cause unexpected behavior in case you are not aware of this." The interrupt flag is restored (sei or cli) afterwards. (Links Codebase64's "safe method" SID detection.)
Playing, and the multispeed split#
- Single speed:
jsr $1003once every screen update (frame). - multispeed tunes have two entry points: "Calls to $1003 parses sequence data and update sounds. Calls to $1006 only updates the sounds." Calling
$1003four times a frame "would get the undesired result of playing the song data four times as quick." So always$1003once per frame, then$1006for the remaining calls:
| Multispeed | Call $1003 | Call $1006 |
|---|---|---|
| 1x | once | never |
| 2x | once | once |
| 4x | once | three times |
| 8x | once | seven times |
Global volume (docs:globalvolume)#
- The SID's global volume register gives "4 bit precision = 16 steps, ranging from $0 to $f" — useful to fade a defMON tune in or out from your own program.
- The player builds the
$D418write out of two self-modified operands:
.sidf_mode_gvol1 = *+1
lda #0
.sidf_mode_gvol2 = *+1
ora #$0f
sta sidbase+$18 ;$D418/54296/SID+24 Select Filter Mode and Volume
.sidf_mode_gvol1is modified by the player (filter mode);.sidf_mode_gvol2"can be modified by you" — "At least in some versions of the defMON player, this is found at location $10b1 in RAM." Set it to$0x("Make sure that the upper nibble is always zero"),$00silent to$0Fmax.
Practical takeaways#
- A packed defMON tune behaves like a standard SID player: init
$1000with song number in A, play$1003per frame — which is why defMON tunes rip into SID files and demos easily. - The
$1003/$1006split is the general multispeed pattern (sequencer once, sound updates N times per frame) made explicit as two entry points — worth citing on multispeed and sid-player-routine. - Fade-outs are a one-byte poke:
$10B1=$00–$0F(version-dependent address; upper nibble must stay 0 because the player ORs in the filter mode bits for$D418). - The interrupt-disabling SID-model detection in init is the classic integration trap: init the tune before setting up raster IRQs, or expect a hiccup.
Notable quotes#
- "The interface is more or less the same as in 90% of all other sid tunes out there."
- "Happy hacking!" (global volume page)
Relevance to the wiki#
Developer-facing facts for the defmon entity (player addresses, packer output format, SID-model auto-detection at init) and concrete numbers for sid-player-routine and multispeed — the two-entry-point convention is the cleanest documented example of how a C64 player separates sequence parsing from per-tick sound updates.
Pages touched#
defmon, sid-player-routine, multispeed, sid-format, sid, frantic, sidechain-pump, levels-and-headroom