Topic: Help with Steve Turner sound effect

While searching around for different sound effects to use / play around with, I found the sound effect engine used in Steve Turner games.  The code I found was

....

;Steve Turner / Hewson Cons 
;sfx engine
;used in Ranarama, Quazatron,IronMan 
;you can use this routine on interrupts
;or in main game cicle

sound     
    ld a,(sonreq) ;new sound play?
    and a
    jr z,nonew  ;No new sound    
;да
    ld (sonnow),a
    dec a
    jr z,noise    ;#01 noise

    ld hl,sfx_data
    dec a
    add a,a
    add a,a
    add a,a
    ld e,a
    xor a
    ld (sonreq),a
    ld d,a
    add hl,de
    ld bc,08
    ld de,sonfrq
    ldir
    jr process

nonew     ld a,(sonnow) ;the old sound is?
    and a
    ret z
    
    dec a    ;continue noise?
    jr nz,process ;continue sound

    jr cnois

noise     ld a,0ah
    ld (sonlen),a
    xor a
    ld (sonreq),a

cnois     ld b,30h

gain    call random
    and 10h
    out (0feh),a
    ld c,02h

make    dec c
    jr nz,make
    djnz gain
    ld hl,sonlen
    dec (hl)
    ret nz
    xor a
    ld (sonnow),a
    ret

process    ld a,(sonfrq)
    ld h,a
    ld a,10h
    ld d,0ffh

sonlp     ld e,h
    out (0feh),a
    xor 10h

freq    dec d
    jr z,mod
    dec e
    jr nz,freq
    jr sonlp

mod    ld a,(soncfg)
    add a,h
    ld (sonfrq),a
    ld hl,sonmod
    dec (hl)
    ret nz
    ld hl,sonlen
    dec (hl)
    jr nz,modify
    xor a
    ld (sonnow),a
    ld a,(sonnex)
    and a
    ret z
    ld (sonreq),a
    ret

modify    ld a,(sobrsf)
    ld c,a
    ld a,(sontyp)
    and a
    jr z,reset
    dec a
    jr z,typ1
    dec a
    jr z,typ2

typoth    ld a,(soncfg)
    neg
    ld (soncfg),a
    jr mode

typ2    inc c
    inc c
    ld a,c
    ld (sobrsf),a
    jr reset

typ1    dec c
    dec c
    ld a,c
    ld (sobrsf),a
    jr reset

reset     ld a,c
    ld (sonfrq),a

mode    ld a,(sonrnd)
    ld (sonmod),a
    ret

random    push hl
    ld hl,(rnseed)
    inc hl
    ld a,h
    and 03
    ld h,a
rok    ld (rnseed),a
    ld a,r
    xor (hl)
    pop hl
    ret

rnseed    defw 1000h

sonfrq    defb 00    ;inital frequency
soncfg    defb 00    ;frequency change rate
sonmod    defb 00    ;number of sound modulations
sonlen    defb 00    ;number of times to repeat
sontyp    defb 00    ;modulate type
            ;0 sawtooth
            ;1 2nd mod down
            ;2 2nd mod up
            ;3+ triangle
sobrsf    defb 00    reset frequency
sonrnd    defb 00    ;change rate of reset frequency
sonnex    defb 00    ;linked sfx
sonnow    defb 00    ;what is being played
sonreq    defb 00    ;which effect?


sfx_data    
;here all souned excepts number 1 reserved for random noise     
;    defb       0,   5,   5,   1,   0,   0,   0,   0
;    defb     28h,   5, 0Ah,   1,   0,   0,   0,   0
;    defb       0, 80h, 1Eh,   1,   0,   0,   0,   0
;    defb           0,   2, 1Eh,   1,   0,   0,   0,   0
;    defb           0, 7Dh, 20h,   1,   0,   0,   0,   0
;    defb     0FFh, 83h, 20h,   1,   0,   0,   0,   0
;    defb     0FFh, 83h, 28h, 20h,   1, 3Ch,   1,   0
;    defb     0F0h,0F0h,   8,   3,   0, 3Ch,   6,   0
;    defb           2, 80h, 0Ah,   1,   0,   0,   0,   0
;    defb       28h,0FAh,   8,   1,   0,   0,   0,   0
;    defb     0FAh, 2Ch,   6, 0Ah,   1, 5Ah,   1,   0
;    defb           0,0FCh, 14h,   8,   1, 50h,   8,   0
;    defb     0E6h,0E6h,   4,   1,   1,   0,   0,   0
;    defb       2Dh, 43h, 14h,   1,   1,   0,   0,   0

Now to the real question(s).  I tried placing this in a C wrapper for usage in Z88DK, so I could call the effects within a single call.  It appears according to the comments that when this is called, only produces a small portion of the sound and returns back to the main loop. 

Can this be easily changed?

What would be more code friendly within Z88dk is to outpulse the entire sound at once and then return back to the game.  I realize that the game would pause while the effect takes place, I'm OK with that, just produce a really short sound while in action.

In Z88dk, I pass onto an assembly routine, L for char, HL for int and DEHL for long.  I am currently just sending L to the assembly and passing that onto a.  My wrapper for this is:

extern void __FASTCALL__ SFX(unsigned char fx) 
{
#asm
    
     ld a,l            ;32758
     ;rest of STEVE TURNER code ....

#endasm
}

Is that proper?  Sorry I am extremely weak on assembly and was hoping that someone much more experienced could help me out on this.

Thank you.

Andy

Re: Help with Steve Turner sound effect

It is possible to modify, but this sound effect approach specifically designed to be called repeatedly each interrupt or each game loop - to play sounds alongside the gameplay, in trade for (relatively) poor sound quality.

A shameless plug, you can use my BeepFX routines that is capable to much more sophisticated effects, but stop action while they're playing. As far as I know, it was hooked up to z88dk already: https://github.com/z88dk/z88dk/wiki/beepfx

website - 1bit music - other music - youtube - bandcamp - patreon - twitter (latest news there)

Re: Help with Steve Turner sound effect

Hahaha this made my day:

;да

I always fail to find an elegant way of commenting a conditional jump. I think this is the perfect way.

Other than that, I can only reiterate what Shiru said: This code is meant to be called through an IM2 interrupt, or some other form of loop.
This appears to be the relevant z88dk documentation: https://github.com/z88dk/z88dk/wiki/interrupts

Re: Help with Steve Turner sound effect

I did get it working (kinda) with a little assistance from the original poster of the sound effect engine.  It does seem to work rather well.  I do think that beepFX sounds better, but there's no harm in having other options.  It doesn't sound quite the same as the demo I've seen, but makes noises in the way I almost expect.

Anyway, here's the code I eventually used.

extern void __FASTCALL__ SFX(unsigned char fx) 
{
    #asm    
    ld a, l            ;
    ;//z88dk passes the L register from unsigned char

    
    ld (sonreq),a    ;
    ;//32991 shows 0
    ;//ld (sonnow),a//added

play_sound:
    call sound        ;
    ld a,(sonnow)    ;
    or a            ;
    jr nz, play_sound;
    ret                ;
    ;//return back to C
    
sound:
        ld a,(sonreq) ;play new sound? ;32777
        ;//loads contents of 32991 into register A
        ; 32991 shows 0
        
        
        and a    ;32780
        jr z,nonew  ;NO
        ;jumps to nonew
        
;YES
        ld (sonnow),a
        dec a
        jr z,noise    ;#01 noise

        ld hl,sfxData
        dec a
        add a,a
        add a,a
        add a,a
        ld e,a
        xor a
        ld (sonreq),a
        ld d,a
        add hl,de
        ld bc, 8
        ld de,sonfrq ;33245    <--start freq
        ldir        ;32809
        jr process

    nonew:
        ld a,(sonnow);32813
        
        ;//and the old sound is?
        ;//loads contents of 32990 into register A

        and a
        ret z
        
        dec a    ;//continue noise?
        jr nz,process ;//continue sound

        jr cnois

    noise:
        ld a,0xA
        ld (sonlen),a
        xor a
        ld (sonreq),a

    cnois:
        ld b,0x30

    gain:
        call random
        and 0x10
        out (0xfe),a
        ld c,2

    make:
        dec c
        jr nz,make
        djnz gain
        ld hl,sonlen
        dec (hl)
        ret nz
        xor a
        ld (sonnow),a
        ret

    process:
        ld a,(sonfrq)    ;<--start freq
        ld h,a
        ld a,0x10
        ld d,0xff

    sonlp:
        ld e,h
        out (0xfe),a
        xor 0x10

    freq:
        dec d
        jr z,mod
        dec e
        jr nz,freq
        jr sonlp

    mod:
        ld a,(soncfg)
        add a,h
        ld (sonfrq),a ;        <--start freq
        ld hl,sonmod
        dec (hl)
        ret nz
        ld hl,sonlen
        dec (hl)
        jr nz,modify
        xor a
        ld (sonnow),a
        ld a,(sonnex)
        and a
        ret z
        ld (sonreq),a
        ret

    modify:
        ld a,(sobrsf)
        ld c,a
        ld a,(sontyp)
        and a
        jr z,reset
        dec a
        jr z,typ1
        dec a
        jr z,typ2

    typoth:
        ld a,(soncfg)
        neg
        ld (soncfg),a
        jr mode

    typ2:
        inc c
        inc c
        ld a,c
        ld (sobrsf),a
        jr reset

    typ1:
        dec c
        dec c
        ld a,c
        ld (sobrsf),a
        jr reset

    reset:
        ld a,c
        ld (sonfrq),a    ;<--start freq

    mode:
        ld a,(sonrnd)
        ld (sonmod),a
        ret

    random:
        push hl
        ld hl,(rnseed)
        inc hl
        ld a,h
        and 3
        ld h,a
        
    rok:
        ld (rnseed),a
        ld a,r
        xor (hl)
        pop hl
        ret

rnseed:    defw 0x1000

sonfrq:    defb sfxData    ;start frequency        
soncfg:    defb sfxData+1    ;frequency change
sonmod:    defb sfxData+2    ;change times
sonlen:    defb sfxData+3    ;repeat times
sontyp:    defb sfxData+4    ;modulate type
                ;0 sawtooth
                ;1 2nd mod down
                ;2 2nd mod up
                ;3+ triangle
sobrsf:    defb sfxData+5    ;reset frequency
sonrnd:    defb sfxData+6    ;change reset temp
sonnex:    defb sfxData+7    ;linked sfx
    
sonnow:    defb 0    ;which effect playing
sonreq:    defb 0    ;we have an effect


;here all sounds excepts number 1 reserved for random noise
sfxData:
defb 0, 5, 5, 1, 0, 0, 0, 0;SFX 2
defb 40, 5, 10, 1, 0, 0, 0, 0;SFX 3
defb 0, 128, 30, 1, 0, 0, 0, 0;SFX 4
defb 0, 2, 30, 1, 0, 0, 0, 0;SFX 5
defb 0, 125, 32, 1, 0, 0, 0, 0;SFX 6
defb 255, 131, 32, 1, 0, 0, 0, 0;SFX 7
defb 255, 131, 40, 32, 1, 60, 1, 0;SFX 8
defb 240, 240, 8, 3, 0, 60, 6, 0;SFX 9
defb 2, 128, 10, 1, 0, 0, 0, 0;SFX 10
defb 40, 250, 8, 1, 0, 0, 0, 0;SFX 11
defb 250, 44, 6, 10, 1, 90, 1, 0;SFX 12
defb 0, 252, 20, 8, 1, 80, 8, 0;SFX 13
defb 230, 230, 4, 1, 1, 0, 0, 0;SFX 14
defb 45, 67, 20, 1, 1, 0, 0, 0;SFX 15
defb 64,  5,  10,  1,  0,  0,  0,  0;SFX 16
defb 40,  5,  10,  1,  0,  0,  0,  0;SFX 17
defb 64,  5,  20,  1,  0,  0,  0,  0;SFX 18
defb 20,220,  64,  1,  3,  10, 1,  0;SFX 19
defb 64,  4,  32,  1,  3,  96,  0,  2;SFX 20
defb 255,131, 32, 1, 0, 0, 0, 0;SFX 21
defb 240, 240, 8, 3, 0, 60, 6, 0;SFX 22
defb 2,120, 10, 1, 0, 0, 0, 0;SFX 23
defb 40,250, 8, 1, 0, 0, 0, 0;SFX 24
defb 250, 44, 6, 10, 1, 132, 1, 0;SFX 25
defb 0, 252, 20, 8, 1, 80, 8, 0;SFX 26
defb 230,230, 4, 1, 1, 0, 0, 0;SFX 27

#endasm
}