Short beeper routines in assembly
Re: Short beeper routines in assembly
I don't suppose anyone can improve on my naff page turning sound?
It's for use on the tape magazine, would be credited natch.
It's for use on the tape magazine, would be credited natch.
Re: Short beeper routines in assembly
Well, I gave it a go previously, but decided not to post it in the end as I didn't really like the result. Seems like it was auto-saved as a draft, sooo here
Code: Select all
SFX
ld hl,0
ld de,#0710
ld bc,2
ld lx,#18
call .loop
ld c,24
ld lx,#06
.loop
ld a,(hl)
inc hl
cp c
sbc a
and e
or d
out (#FE),a
djnz .loop
dec lx
jr nz,.loop
ret
Inactive account
Re: Short beeper routines in assembly
Much better than mine, thanks.
Are you still okay to be credited as 'owner' of the noise if I go with this? I'm using IX as a string pointer, so while it would be easy enough to PUSH it I'm trying to minimise having to do so.
Also, do you think changing ld d,6 to 24 makes it better or too close to masticating crisps?
Why did you use ixl? Timing reasons, or just because you used every other register?
Are you still okay to be credited as 'owner' of the noise if I go with this? I'm using IX as a string pointer, so while it would be easy enough to PUSH it I'm trying to minimise having to do so.
Also, do you think changing ld d,6 to 24 makes it better or too close to masticating crisps?
Why did you use ixl? Timing reasons, or just because you used every other register?
Code: Select all
org 32768
SFX
ld hl,0
ld bc,2
ld d,24
call .loop
ld c,24
ld d,64
.loop
ld a,(hl)
inc hl
cp c
sbc a,a
and 24
or 7
out (254),a
djnz .loop
dec d
jr nz,.loop
ret
Re: Short beeper routines in assembly
I don't think something like this needs a credit at all, so any option is fine of course. For the record, at the core of it is a fairly old trick used in the Tritone engine (and IIRC one more from the 80's), i.e. CP N: SBC A: AND #10. In other words, any values less than N give #10, while values equal to or more than N give 0. Tritone uses it as a kind of hybrid 'timbre/volume control' for square waves, so I thought I might be able to get something similar with the noise, but apparently the result is far less pronounced.
LX, no point really, it's more due to my subconscious habit to speed up innermost loops (use up all registers first, ask questions later). Well, this time it affects the noise pitch. Try both versions, maybe tweak the constants a bit to see which is better. There's no right or wrong about it other than if it sounds good to you.
LX, no point really, it's more due to my subconscious habit to speed up innermost loops (use up all registers first, ask questions later). Well, this time it affects the noise pitch. Try both versions, maybe tweak the constants a bit to see which is better. There's no right or wrong about it other than if it sounds good to you.
Inactive account
Re: Short beeper routines in assembly
If it's any help, the way I generate the combined noise and tone that gives the saws in Buzzsaw+ their 'whine' was to create a high/low square wave, then have a random number generator that whenever it produces a number over a certain threshold, I temporarily invert a bit of the square wave for a small number of cycles.
Now to control the rough 'pitch' of the whine, that's the original square wave. To make it more or less noisy, I move the threshold above which the random number inverts the output, or have it so it can only insert '1s' into the square wave, rather than invert it (so it only affects the low half of the wave). And to adjust the pitch of the noise, I make the random inversion stick around for more or less cycles of my sound function.
But these are prepared in advance and replayed from a buffer, which repeats once it's set up. To make the 'noise' sound more random, the buffer is longer than it needs to be and each time it replays the start position is randomised.
Now to control the rough 'pitch' of the whine, that's the original square wave. To make it more or less noisy, I move the threshold above which the random number inverts the output, or have it so it can only insert '1s' into the square wave, rather than invert it (so it only affects the low half of the wave). And to adjust the pitch of the noise, I make the random inversion stick around for more or less cycles of my sound function.
But these are prepared in advance and replayed from a buffer, which repeats once it's set up. To make the 'noise' sound more random, the buffer is longer than it needs to be and each time it replays the start position is randomised.
Re: Short beeper routines in assembly
Aye it is, in the long term. I don't have enough time to refine a sound routine right now but it's something I started to make progress with then forgot during a 6 month coding lacuna. I tend to avoid doing music/sound as I don't feel I have an affinity for audio anyway, but it's probably similar to when people say 'I can't draw' and I never believe them.
There are some amazing sound support packages out there but spot effects and music are IMO the most neglected area in ZX Software these days (and I'm at least as guilty as anyone).
Re: Short beeper routines in assembly
Some disassembly from BLAM:
Code: Select all
sub_9E21: ; CODE XREF: sub_8EA7:loc_8F13p
ld hl, 1F40h
ld c, 0D0h ; 'Р'
loc_9E26: ; CODE XREF: sub_9E21+Fj
ld a, (hl)
and 18h
out (0FEh), a
ld b, c
loc_9E2C: ; CODE XREF: sub_9E21:loc_9E2Cj
djnz $
inc hl
inc c
jr nz, loc_9E26
ret
; End of function sub_9E21
; =============== S U B R O U T I N E =======================================
sub_9E33: ; CODE XREF: sub_C746+72p
ld b, 64h ; 'd'
loc_9E35: ; CODE XREF: sub_9E33+11j
xor a
out (0FEh), a
push bc
loc_9E39: ; CODE XREF: sub_9E33:loc_9E39j
djnz $
pop bc
ld a, 0F8h ; 'ш'
out (0FEh), a
push bc
loc_9E41: ; CODE XREF: sub_9E33:loc_9E41j
djnz $
pop bc
djnz loc_9E35
ret
; End of function sub_9E33
; =============== S U B R O U T I N E =======================================
sub_9E47: ; CODE XREF: sub_CA18+3p
ld b, 64h ; 'd'
loc_9E49: ; CODE XREF: sub_9E47+18j
xor a
out (0FEh), a
push bc
ld a, r
ld b, a
loc_9E50: ; CODE XREF: sub_9E47+Bj
nop
nop
djnz loc_9E50
pop bc
ld a, 0F8h ; 'ш'
out (0FEh), a
push bc
loc_9E5A: ; CODE XREF: sub_9E47+15j
nop
nop
djnz loc_9E5A
pop bc
djnz loc_9E49
ret
Re: Short beeper routines in assembly
Here's a simulation of the Chuckie Egg 'farty collect' sound. After looking at the code and the weird interrupt, I thought I'd never unravel it, but as long as you know which bit is making the noise, you can use the debugger to count the # of tstates in between and approximate. Close enough?
Code: Select all
org 32768
cbmain:
ld b,60 ;it last slightly more than a second, and each loop on average is a bit more than a full frame
cbbeep: push bc
call chuckiebeep
call chuckiedelay
ld hl,ccounter
inc (hl)
pop bc
djnz cbbeep
ret
;
chuckiedelay:
ld a,(ccounter)
and 7
add a,a
ld c,a
ld b,0
ld hl,cdelays
add hl,bc
ld c,(hl)
inc hl
ld b,(hl)
cdlp: dec bc
ld a,b
or c
jr nz,cdlp
ret
;
chuckiebeep:
ld a,(ccounter)
and 7
ld c,a
ld b,0
ld hl,chuckbeeps
add hl,bc
ld h,(hl) ;H is 37,33,29,25,21,17,13,9 cycled
ld l,2 ;L is always 2
cblp2: ld a,16 ;arrive H tone, L always 2, this is exactly the same as the Chuckie Egg sound engine
out (254),a
ld b,h
cblp0: djnz cblp0
xor a
out (254),a
ld b,h
cblp1: djnz cblp1
dec l
jr nz,cblp2
ret
;
ccounter: db 0
chuckbeeps: db 37,33,29,25,21,17,13,9 ;the chuckie egg code does this as SUBs
cdelays: dw 1580,1988,1035,1433,476,860,2260,243 ;approximate BC loopcounter for no of tstates that pass between beeps
;
Re: Short beeper routines in assembly
Yep, just compared it to the original, to my knackered ears it's a smidgen slower and lower pitched than the game, but otherwise spot on.
My Speccy site: thirdharmoniser.com
Re: Short beeper routines in assembly
Cheers. I can't spot a difference, but I don't have a good ear for these things.
Can anyone accurately compare using technology? And understand how the delays should change to match?
Re: Short beeper routines in assembly
I just ripped this tune from a game. I won't spoil the surprise by saying which.
The code isn't exactly the same, just a similar player and the music data was easily halved in size. It could probably be reduced ever further as there aren't that many combinations.
The code isn't exactly the same, just a similar player and the music data was easily halved in size. It could probably be reduced ever further as there aren't that many combinations.
Code: Select all
org 32768
musicbeep:
halt
halt
halt
halt
ld hl,(musiccount)
ld h,0
add hl,hl
ld de,musictab
add hl,de
ld e,(hl)
inc hl
ld c,(hl)
ld b,0
ld d,b
ld a,e
cp 255
call z,resettune
or a
call nz,musiclp
ld hl,musiccount
inc (hl)
jr musicbeep
;
resettune:
xor a
ld (musiccount),a
ld de,(musictab)
ld c,d
ld b,0
ld d,b
ld a,e
ret
;
musiccount: db 0
;
musiclp: ld a,0
out (254),a
call delay
ld a,16
out (254),a
call delay
dec de
ld a,d
or e
jr nz,musiclp
ret
;
delay: push bc
delp: dec bc
ld a,b
or c
jr nz,delp
pop bc
ret
;
musictab:
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 43,38
DEFB 46,35
DEFB 0,0
DEFB 53,30
DEFB 46,35
DEFB 53,30
DEFB 0,0
DEFB 25,65
DEFB 0,0
DEFB 25,65
DEFB 0,0
DEFB 25,65
DEFB 22,73
DEFB 21,78
DEFB 34,48
DEFB 34,48
DEFB 32,50
DEFB 34,48
DEFB 0,0
DEFB 38,43
DEFB 43,38
DEFB 46,35
DEFB 43,38
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 30,53
DEFB 28,58
DEFB 25,65
DEFB 22,73
DEFB 22,73
DEFB 20,80
DEFB 18,90
DEFB 16,103
DEFB 0,0
DEFB 18,90
DEFB 22,73
DEFB 21,78
DEFB 25,65
DEFB 22,73
DEFB 28,58
DEFB 25,65
DEFB 30,53
DEFB 28,58
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 0,0
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 34,48
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 34,48
DEFB 38,43
DEFB 0,0
DEFB 29,55
DEFB 0,0
DEFB 29,55
DEFB 0,0
DEFB 38,43
DEFB 34,48
DEFB 29,55
DEFB 53,30
DEFB 53,30
DEFB 38,43
DEFB 29,55
DEFB 53,30
DEFB 53,30
DEFB 38,43
DEFB 43,38
DEFB 0,0
DEFB 34,48
DEFB 0,0
DEFB 34,48
DEFB 0,0
DEFB 38,43
DEFB 43,38
DEFB 46,35
DEFB 43,38
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 30,53
DEFB 28,58
DEFB 25,65
DEFB 22,73
DEFB 22,73
DEFB 20,80
DEFB 18,90
DEFB 16,103
DEFB 0,0
DEFB 18,90
DEFB 22,73
DEFB 21,78
DEFB 25,65
DEFB 22,73
DEFB 28,58
DEFB 25,65
DEFB 30,53
DEFB 28,58
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 0,0
DEFB 255,255
endmusic:
Re: Short beeper routines in assembly
The
music has irritated me for over 30 years as there are some annoying extra pauses between the notes that I don't think should be there. Whenever I've played the game it's made me more twitchy than piratey.
I reckon the gaps should be something a bit more like:
Spoiler
Booty
I reckon the gaps should be something a bit more like:
Code: Select all
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 43,38
DEFB 46,35
DEFB 0,0
DEFB 53,30
DEFB 46,35
DEFB 53,30
DEFB 0,0
DEFB 25,65
DEFB 0,0
DEFB 25,65
DEFB 0,0
DEFB 25,65
DEFB 22,73
DEFB 21,78
DEFB 34,48
DEFB 34,48
DEFB 32,50
DEFB 34,48
DEFB 0,0
DEFB 38,43
DEFB 43,38
DEFB 46,35
DEFB 43,38
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 30,53
DEFB 28,58
DEFB 25,65
DEFB 22,73
DEFB 22,73
DEFB 20,80
DEFB 18,90
DEFB 16,103
DEFB 18,90
DEFB 22,73
DEFB 21,78
DEFB 25,65
DEFB 22,73
DEFB 28,58
DEFB 25,65
DEFB 30,53
DEFB 28,58
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 34,48
DEFB 28,58
DEFB 46,35
DEFB 46,35
DEFB 34,48
DEFB 38,43
DEFB 0,0
DEFB 29,55
DEFB 0,0
DEFB 29,55
DEFB 0,0
DEFB 38,43
DEFB 34,48
DEFB 29,55
DEFB 53,30
DEFB 53,30
DEFB 38,43
DEFB 29,55
DEFB 53,30
DEFB 53,30
DEFB 38,43
DEFB 43,38
DEFB 0,0
DEFB 34,48
DEFB 0,0
DEFB 34,48
DEFB 0,0
DEFB 38,43
DEFB 43,38
DEFB 46,35
DEFB 43,38
DEFB 38,43
DEFB 34,48
DEFB 38,43
DEFB 34,48
DEFB 30,53
DEFB 28,58
DEFB 30,53
DEFB 28,58
DEFB 25,65
DEFB 22,73
DEFB 22,73
DEFB 20,80
DEFB 18,90
DEFB 16,103
DEFB 18,90
DEFB 22,73
DEFB 21,78
DEFB 25,65
DEFB 22,73
DEFB 28,58
DEFB 25,65
DEFB 30,53
DEFB 28,58
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 22,73
DEFB 0,0
DEFB 255,255
My Speccy site: thirdharmoniser.com
Re: Short beeper routines in assembly
I think it sounds better. I can't really pick out why and which bits though. But no matter how good it gets—such a short loop of that track will drive anyone crackers.
Re: Short beeper routines in assembly
I don't suppose anyone has a disasm of any of the digitised speech, or the beeper music in Ghostbusters?
My attempts so far sound like heavy furniture being dragged...
My attempts so far sound like heavy furniture being dragged...
Re: Short beeper routines in assembly
What exactly are you trying to do ? I diassembled of digitised music od Twinz! time ago. I don't have listing anymore but I remember it was rather easy to understand.
For example, I have tried to diassemply effects in Starquake
and firelord and I never got even rough idea how it works.
Judging by the Booty sound routine, are you aware that aligning time between OUTs to multiply od 8T improves sound quality ?
Proud owner of Didaktik M
Re: Short beeper routines in assembly
It's something for Woot. Ultra top secret.
I couldn't unravel these either. It's interesting that some of the most elaborate sounds have a simple engine (e.g. Dynamite Dan), but other games with simpler sounds are more cryptic. Atic Atac is quite hard too—I got close but it's not quite good enough.For example, I have tried to diassemply effects in Starquake and firelord and I never got even rough idea how it works.
I don't understand—so probably not! Can you elaborate, perhaps with a code example?Judging by the Booty sound routine, are you aware that aligning time between OUTs to multiply od 8T improves sound quality?
Re: Short beeper routines in assembly
OK. My understanding is that you have issues with too much noise while replaying sampled speech. Is that correct ?
Port 254 is contended and ULA may insert few ticks when you try write (or read) to (from) port 254. Solution is simple, in your sound loop, be sure that the time between two consecutive writes to port 254 is divisible by 8.
This contention is notable when you try to generate pure tone but in that case you still get a tone, just with slight glitches. But sample replay is more noisy by its nature and avoiding contetion will improve sound quality.
See also: http://randomflux.info/1bit/viewtopic.php?id=21
I can also add some example later, but right now I should go to job.
Port 254 is contended and ULA may insert few ticks when you try write (or read) to (from) port 254. Solution is simple, in your sound loop, be sure that the time between two consecutive writes to port 254 is divisible by 8.
This contention is notable when you try to generate pure tone but in that case you still get a tone, just with slight glitches. But sample replay is more noisy by its nature and avoiding contetion will improve sound quality.
See also: http://randomflux.info/1bit/viewtopic.php?id=21
I can also add some example later, but right now I should go to job.
Proud owner of Didaktik M
Re: Short beeper routines in assembly
I rechecked the wiki page about I/O contention. Is it just me, or does it have a mistake?
According to the description, "access to ports between 0x4000 and 0x7ffe with the low bit clear (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state."
This seems to be contradicted by the table on the same page, which indicates contention on every T-state when the low bit is set. When it mentions the 'low bit clear', does that refer to the bit being set or reset?
According to the description, "access to ports between 0x4000 and 0x7ffe with the low bit clear (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state."
This seems to be contradicted by the table on the same page, which indicates contention on every T-state when the low bit is set. When it mentions the 'low bit clear', does that refer to the bit being set or reset?
Re: Short beeper routines in assembly
No—I meant that I couldn't do it at all. I wondered if the code was already out there online to save me time.
Brilliant link. Thanks.
Re: Short beeper routines in assembly
I think you are right. IMO it should say “ Access to ports between 0x4000 and 0x7ffe with the low bit SET (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state”djnzx48 wrote: ↑Mon Oct 14, 2019 8:00 am I rechecked the wiki page about I/O contention. Is it just me, or does it have a mistake?
According to the description, "access to ports between 0x4000 and 0x7ffe with the low bit clear (i.e. when the ULA's own port is not being accessed) is subject to contention on every T state."
This seems to be contradicted by the table on the same page, which indicates contention on every T-state when the low bit is set. When it mentions the 'low bit clear', does that refer to the bit being set or reset?
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: Short beeper routines in assembly
That makes more sense. But why is port 0x7fff not included in that range? Should 0x7ffe be changed to 0x7fff, or is that correct as it is?
Re: Short beeper routines in assembly
Yes, it should be included I think. Part of the same mistake.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Waves lapping on the shore beeper sound
I'm trying to approximate the soothing sound of gentle waves lapping on a tropical shore, but my attempts so far are closer to a stormy day at Heysham. I'm just posting this in case anyone can suggest improvements or even post better code examples*. It has to be a shortish piece of code, so no huge samples.
*to be clear: I want to make it sound more gentle.
*to be clear: I want to make it sound more gentle.
Code: Select all
org 32768 ;might be slightly better in contended memory
mloop: call wave
call wavelaprumble ;(superfluous?)
call betweenwavepause
jr mloop
;
betweenwavepause:
ld b,30
call rnd
and 15
add a,b
ld b,a
bwplp: halt
djnz bwplp
ret
;
wavelaprumble:
ld bc,10000
bwlp: call rnd
and 16
out (254),a
dec bc
ld a,b
or c
jr nz,bwlp
ret
;
wave: ld c,63
ld de,1024
ld hl,0
main: call rnd
and 16
out (254),a
ld e,c
dlp: dec e
jr nz,dlp
dlp1: dec de
ld a,d
or a
jr nz,miss
ica: dec c
ret z
miss: ld a,d
or e
jr nz,main
ld a,2
out (254),a
ret
;
;PATRIK RAK's XOR SHIFT RND generator
rnd:
push hl
push de
rsd0: ld hl,0xA280 ; yw -> zt
rsd1: ld de,0xC0DE ; xz -> yw
ld (rnd+6),hl ; x = y, z = w
ld a,l ; w = w ^ ( w << 3 )
add a,a
add a,a
add a,a
xor l
ld l,a
ld a,d ; t = x ^ (x << 1)
add a,a
xor d
ld h,a
rra ; t = t ^ (t >> 1) ^ w
xor h
xor l
ld h,e ; y = z
ld l,a ; w = t
ld (rnd+3),hl
pop de
pop hl
ret
;