Sound Effects and PlaySound - HoraceAndTheSpider/Bloodwych-68k GitHub Wiki

Sound effects and PlaySound

Bloodwych SPS 439 stores five 8SVX sound samples in the executable. The game does not pass a sample address to the playback routine. Instead, callers put a zero-based sound ID in D0 and call PlaySound.

The routine is at memory address $8910 (binary offset $858C) in the SPS 439 source. It uses the ID to select one of six entries in AudioSampleOffsets, so IDs 0 and 1 are two sounds located inside the first sample file rather than two separate files.

Sound IDs

The following names describe the IDs used by the source. The broad sample descriptions are also consistent with the extracted-sample notes in the project archive.

ID in D0 Source selection Sound description Evidence / known callers
$00 sample1.sound; period $28 Switch or interface click Played during startup and the wall-switch action path. The extracted sample is documented as “Click / Switch”.
$01 sample1.sound; period $9B Secondary click variant This is the second playback entry within sample1.sound; the exact gameplay event for this variant is not isolated in the current SPS 439 call trace.
$02 sample2.sound; period $5D Attack or fighting clink Played by the physical-attack routine at adrCd0061DA. The extracted sample is documented as “Clink / Fighting”.
$03 sample3.sound; period $28 Character death Played from the character death-state handling path at adrCd0024BE. The extracted sample is documented as “Character Death”.
$04 sample4.sound; period $49 Spell or fireball sound Selected by the special-effect path at adrCd001E08. The extracted sample is documented as “Spell Sound / Fireball”.
$05 sample5.sound; period $49 Alternative spell sound Used by several spell, crystal, and Vivify-machine effect paths. The extracted sample is documented as “Alternative Spell Sound”.

The descriptions distinguish the sound resources and their call-site context; they should not be read as a claim that every use of a shared sample has a different recording.

The PlaySound routine

The routine uses Paula audio channel 0. In simplified form, its operation is:

PlaySound:
        move.w  d1,-(sp)                 ; preserve the caller's D1
        move.w  #$0001,_custom+dmacon.l  ; stop channel 0 DMA
        move.w  #$0080,_custom+intena.l  ; disable the audio interrupt
        asl.w   #$02,d0                  ; six entries, four bytes each
        lea     SFX_AudioSample_1.l,a0
        add.w   AudioSampleOffsets(pc,d0.w),a0
        move.w  AudioSampleOffsets+$2(pc,d0.w),d0
        lea     $0030(a0),a0             ; skip the 8SVX header
        move.w  -$0002(a0),d1            ; sample length before the body
        lsr.w   #$01,d1                  ; Paula length is in words
        asl.w   #$02,d0                  ; convert the period value
        move.l  a0,_custom+aud.l
        move.w  d1,_custom+aud0+ac_len.l
        move.w  #$0040,_custom+aud0+ac_vol.l
        move.w  d0,_custom+aud0+ac_per.l
        move.w  (a0),_custom+aud0+ac_dat.l
        ; short delay, enable channel 0 DMA, short delay
        ; clear the request, restore interrupts and restore D1
        rts

The real routine is deliberately retained as the authoritative source in asm/BLOODWYCH439.asm; the extract above shows the data flow rather than every timing instruction.

Before programming Paula, the routine advances by $30 bytes from the selected sound-file base. This skips the 8SVX header and leaves A0 pointing at the sample body. The word immediately before that body supplies the sample length. The routine halves that value because Paula's length register counts words, not bytes.

The second word in each AudioSampleOffsets pair is loaded as a playback period and multiplied by four before being written to aud0+ac_per. This is a sample-specific playback-rate setting, not another byte offset.

AudioSampleOffsets

Each table entry is four bytes:

  1. a word offset from SFX_AudioSample_1 to the containing sound file;
  2. a Paula playback-period value, multiplied by four before it is written to aud0+ac_per; and
  3. the next entry begins immediately after those two words.

In source form, the table is:

AudioSampleOffsets:
        dc.w SFX_AudioSample_1-SFX_AudioSample_1 ; ID 0: $0000
        dc.w $0028                            ; ID 0 period
        dc.w SFX_AudioSample_1-SFX_AudioSample_1 ; ID 1: $0000
        dc.w $009B                            ; ID 1 period
        dc.w SFX_AudioSample_2-SFX_AudioSample_1 ; ID 2: $0084
        dc.w $005D                            ; ID 2 period
        dc.w SFX_AudioSample_3-SFX_AudioSample_1 ; ID 3: $0646
        dc.w $0028                            ; ID 3 period
        dc.w SFX_AudioSample_4-SFX_AudioSample_1 ; ID 4: $1ECE
        dc.w $0049                            ; ID 4 period
        dc.w SFX_AudioSample_5-SFX_AudioSample_1 ; ID 5: $3684
        dc.w $0049                            ; ID 5 period

The table begins at memory address $8938 (binary offset $85B4). The first words also show that the five sound files are stored sequentially: sample 2 starts $84 bytes after sample 1, sample 3 starts $646 bytes after sample 1, sample 4 starts $1ECE, and sample 5 starts $3684.

Extracted sound resources

The SPS 439 extraction names these files using the .sound faux-extension. They are the original binary sample blocks, not converted or normalised audio files.

File Binary offset Size Source label
data/BLOODWYCH439-clean/sfx/sample1.sound $5409E $84 SFX_AudioSample_1
data/BLOODWYCH439-clean/sfx/sample2.sound $54122 $5C2 SFX_AudioSample_2
data/BLOODWYCH439-clean/sfx/sample3.sound $546E4 $1888 SFX_AudioSample_3
data/BLOODWYCH439-clean/sfx/sample4.sound $55F6C $17B6 SFX_AudioSample_4
data/BLOODWYCH439-clean/sfx/sample5.sound $57722 $D82 SFX_AudioSample_5

These are sequential in the original binary. Their source memory labels are $54422, $544A6, $54A68, $562F0, and $57AA6 respectively.

Call-site examples

The fixed-ID call sites in SPS 439 include:

moveq   #$00,d0
jsr     PlaySound.l       ; startup click

moveq   #$02,d0
bsr     PlaySound          ; physical attack

moveq   #$01,d0
bsr     PlaySound          ; wall-feature / door click

moveq   #$03,d0
jsr     PlaySound.l       ; character death path

moveq   #$04,d0
jsr     PlaySound.l       ; spell effect

moveq   #$05,d0
bsr     PlaySound          ; alternative spell/effect sound

Some trigger code loads a value from Trigger_WaitFlag into D0 and then branches to PlaySound. That value is dynamic, so it should not be treated as a new fixed sound ID without tracing the individual trigger handlers.

Source references

The primary evidence is the SPS 439 disassembly:

  • asm/BLOODWYCH439.asm, PlaySound at $8910 and AudioSampleOffsets at $8938;
  • asm/BLOODWYCH439_relabel_data.asm, where the sound resources are emitted as SFX_AudioSample_1 through SFX_AudioSample_5;
  • _archive/data/bw-sfx/ReadMe.txt, which records the descriptions of the five extracted samples.

The routine uses standard Amiga Paula registers (DMACON, INTENA, INTREQ, AUD, and AUD0) and an IFF 8SVX-style sample layout. The sound selection and call-site meanings above are Bloodwych-specific; the DMA and sample playback mechanism is conventional Amiga audio handling.