changeset 52:47ffee6789b1

Decoded sound routines and related variables. Decoded all the sound routines and their related variables. Much of the description is probably inaccurate since detailed analysis of the routines is needed to determine their exact characteristics. The general overall descriptions should be correct, however.
author William Astle <lost@l-w.ca>
date Sat, 27 Dec 2014 19:04:00 -0700
parents a9e81b2a8672
children bb39e4af7e21
files dod.s
diffstat 1 files changed, 266 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/dod.s	Sat Dec 27 16:21:57 2014 -0700
+++ b/dod.s	Sat Dec 27 19:04:00 2014 -0700
@@ -297,17 +297,18 @@
 polyfirst	rmb 1				; for rendering images - set if this is the first vertex
 lastunscalex	rmb 2				; most recent unscaled X coordinate for rendering
 lastunscaley	rmb 2				; most recent unscaled Y coordinate for rendering
-V256		rmb 2				; sound:
-		rmb 1				; *unused*
-V259		rmb 1				; sound:
+soundseqseed	rmb 2				; sound: sequence generator seed
 		rmb 1				; *unused*
-V25B		rmb 2				; sound:
-V25D		rmb 2				; sound:
-V25F		rmb 2				; sound:
+sndtemp		rmb 1				; sound: temporary storage for dac value
+		rmb 1				; *unused*
+sndampmult	rmb 2				; sound: amplitude multiplier for volume slides (MSB is used)
+sndampstep	rmb 2				; sound: amplitude step for volume slides
+soundrepeat	rmb 1				; sound: repeat counter
+		rmb 1				; *unused*
 soundvol	rmb 1				; sound: volume multiplier for sound playing
-V262		rmb 1				; sound:
-V263		rmb 2				; sound:
-V265		rmb 2				; sound:
+soundrepeat2	rmb 1				; sound: repeat counter for scorpion, wraith, and viper sounds
+sndlowtonedel	rmb 2				; sound: low tone wave delay for dual tone generator
+sndhitonedel	rmb 2				; sound: high tone wave delay for dual tone generator
 		rmb 4				; *unused*
 randomseed	rmb 3				; random number generator seed value
 effectivelight	rmb 1				; effective light level in dungeon
@@ -1505,6 +1506,10 @@
 		coma				; invert mask
 		sta statusarea+6		; set background mask for status line
 		rts				; return to caller
+; From here until the SWI routine jump table is the sound handling system. Any frequencies listed in the
+; descriptions of these routines are for illustrative purposes as they are almost certainly wrong to a
+; greater or lesser degree.
+;
 ; swi 27 routine
 ; play a sound specified by the immediate identifier
 LC7C8		ldx 12,s			; fetch return address
@@ -1538,241 +1543,292 @@
 		fdb LC8DA			; sound 15 - shield sound
 		fdb LC8A6			; sound 16 - sword sound
 		fdb LC8B2			; sound 17 - torch sound
-		fdb LC93F			; sound 18 - attack hit
-		fdb LC8E6			; sound 19 - ??? attack miss
-		fdb LC872			; sound 20 - ??? walk into wall sound
+		fdb LC93F			; sound 18 - attack hit (player)
+		fdb LC8E6			; sound 19 - attack hit (creature)
+		fdb LC872			; sound 20 - walk into wall sound
 		fdb LC86D			; sound 21 - creature death
 		fdb LC88A			; sound 22 - wizard fade sound
-; sound 12
-LC80A		ldu #LC823			; point to 144Hz base tone
+; sound 12 - flask
+LC80A		ldu #LC823			; point to 410Hz base tone
 		lda #4				; repeat sound 4 times
 		bra LC816			; go do the sound
-; sound 13
-LC811		ldu #LC81F			; point to 288Hz base tone
+; sound 13 - ring
+LC811		ldu #LC81F			; point to 780Hz base tone
 		lda #10				; repeat sound 10 times
-LC816		sta V25F			; set repeat counter
+LC816		sta soundrepeat			; set repeat counter
 LC818		jsr ,u				; make a sound
-		dec V25F			; have we done enough of them?
+		dec soundrepeat			; have we done enough of them?
 		bne LC818			; brif not
 		rts
 ; These routines produce a "sliding" tone starting at the base frequency. The specified base
 ; frequency is a rough estimate. The tones are created using square waves. After each full wave,
 ; the delay in reduced by one which increases the frequency. The last cycle is with the delay
-; equal to 1 which yields an approximate frequency of 9520Hz.
-LC81F		ldx #$40			; set low frequency of sliding tone to ~288Hz
-		fcb $10
-LC823		ldx #$80			; set low frequency of sliding tone to ~144Hz
+; equal to 1 which yields an approximate frequency of 9520Hz. Because the delays become progressively
+; shorter, the lower frequency range lasts longer than the higher frequency range.
+;
+; The "fcb $10" instructions turn the following LDX into LDY, effecting skipping them.
+LC81F		ldx #$40			; set low frequency of sliding tone to ~782Hz
 		fcb $10
-; sound 14
-LC827		ldx #$100			; set low frequency of sliding tone to ~72Hz
+LC823		ldx #$80			; set low frequency of sliding tone to ~413Hz
 		fcb $10
-; sound 0
-LC82B		ldx #$20			; set low frequency of sliding tone to ~566Hz
-LC82E		bsr LC835			; do one square wave
+; sound 14 - scroll
+LC827		ldx #$100			; set low frequency of sliding tone to ~212HzHz
+		fcb $10
+; sound 0 - spider
+LC82B		ldx #$20			; set low frequency of sliding tone to ~1416Hz
+LC82E		bsr onesquarewave		; do one square wave
 		leax -1,x			; reduce delay (increase frequency)
 		bne LC82E			; brif not yet reached maximum frequency
 		rts
-; Output a square wave with wave time defined by delay in X
-LC835		lda #$ff			; (2~) hold DAC high for delay in X
-		bsr LC869			; (7~)
+; Output a square wave with wave time defined by delay in X.
+; The frequency of the wave is per the following table, which is calculated based on the the
+; clock rate of 894886.25 cycles per second and the total time taken for this routine to
+; execute. The total time for this routine to execut is 120+16X cycles where X is the value
+; in X. So, the table is as follows. The X values are in hexadecimal. The frequency values
+; are in decimal.
+;
+; X	Frequency
+; 0001	6580Hz
+; 0020	1416Hz
+; 0040	782Hz
+; 0080	413Hz
+; 0100	212Hz
+; FFFF	0.8533Hz
+onesquarewave	lda #$ff			; (2~) hold DAC high for delay in X
+		bsr setdacdel			; (7~)
 		clra				; (2~) hold DAC low for delay in X
-		bra LC869			; (3~)
-; sound 3
-; Output a series of 16 ascending tones with a base frequency descending from 14.5Hz to 9Hz.
-LC83C		ldx #$500			; set for an ascending tone from 14.5Hz
-LC83F		bsr LC835			; go make the sound
+		bra setdacdel			; (3~)
+; sound 3 - blob
+; Output a series of 16 ascending tones with a base frequency descending from 43.4Hz to 27.2Hz.
+LC83C		ldx #$500			; set for an ascending tone from 43.4Hz
+LC83F		bsr onesquarewave		; go make the sound
 		leax $30,x			; decrease starting tone frequency by a bit
-		cmpx #$800			; have we reached 9Hz?
+		cmpx #$800			; have we reached 27.2Hz?
 		blo LC83F			; brif not
 		rts
-; sound 6
-LC84A		lda #2
-		skip2
-; sound 8
-LC84D		lda #1
+; sound 6 - scorpion
+LC84A		lda #2				; two bits for scorpion
 		skip2
-; sound 1
-LC850		lda #10
-		sta V262
-LC854		ldy #$c0
-LC858		bsr LC8CE
-		bsr LC8C5
-		leay -1,y
-		bne LC858
-		bsr LC8BA
-		dec V262
-		bne LC854
-		rts
-LC867		bsr LC8CE
-LC869		bsr LC8C5			; (7~) program the DAC
-		bra LC8BD			; (3~) count down delay non-destructively
-; sound 21
-LC86D		ldu #LDBDA
-		bra LC893
-; sound 20
-LC872		ldu #LDBD2
-		bra LC893
-; sound 10, sound 11
-LC877		lda #8
-		sta V25F
-LC87B		bsr LC8CE
-		clra
-		lsrb
-		bne LC882
-		incb
-LC882		tfr d,x
-		bsr LC82E
-		dec V25F
-		bne LC87B
-; sound 22
-LC88A		ldu #LDBD2
-		bsr LC893
-		bsr LC8BA
-		leau 4,u
-LC893		ldx ,u
-LC895		ldy 2,u
-LC898		bsr LC867
-		leay -1,y
-		bne LC898
-		leax 2,x
-		cmpx #$150
-		bne LC895
-		rts
-; sound 16
-LC8A6		jsr LC931
-		fcb $80
-LC8AA		bsr LC922
-		bcs LC8B2
-		bsr LC8C5
-		bra LC8AA
-; sound 17
-LC8B2		jsr LC92E
-		fcb $a0
-LC8B6		bsr LC926
-		bra LC8B6
-LC8BA		ldx #$1000
-LC8BD		pshs x				; (7~) save delay counter
-LC8BF		leax -1,x			; (5~) has timer expired?
-		bne LC8BF			; (3~) brif not
+; sound 8 - wraith
+LC84D		lda #1				; one bit for wraith
+		skip2
+; sound 1 - viper
+; This generates a sequence of sounds at notionally 5524Hz but it uses random amplituds so
+; it's more of a random sound. The sound lasts about 35ms
+LC850		lda #10				; ten bits for viper
+		sta soundrepeat2		; save repeat count
+LC854		ldy #$c0			; number of iterations for tone generation
+LC858		bsr sndseqnext			; (7~) get a sequence value
+		bsr setdac			; (7~) set the dac
+		leay -1,y			; (5~) done enough iterations?
+		bne LC858			; (3~) brif not
+		bsr LC8BA			; delay for 36.6 ms
+		dec soundrepeat2		; done repeats?
+		bne LC854			; brif not
+		rts				; return to caller
+; This entry point takes a delay in X and programs the DAC with a value from the sequence generator.
+; It exits after waiting out the X delay. It uses the MSB of the sequence value.
+setdacseqdel	bsr sndseqnext			; (7~) get a value from the sequence to set the DAC
+; This entry point takes a delay in X and the DAC value in A. It programs the DAC and waits out
+; the delay in X.
+setdacdel	bsr setdac			; (7~) program the DAC
+		bra snddelay			; (3~) count down delay non-destructively
+; sound 21 - creature death
+; This does a slightly longer variation of the last sound for sound 22 below:
+; A bust sliding from 622Hz to 162Hz, frequency shifting every 2.5 waves.
+; This routine spins the sequence 640 times.
+LC86D		ldu #LDBDA			; point to creature death tone generator parameters
+		bra LC893			; go process the sound
+; sound 20 - walk into wall
+; This one uses exactly the same tone as the first half of sound 22.
+; That is a short burst sliding from 405Hz to 162Hz, frequency shifting every half wave
+; This routine spins the sequence 104 times.
+LC872		ldu #LDBD2			; point to the generation specification for the sound
+		bra LC893			; go generate the sound
+; sound 10, sound 11 - wizard's image, wizard
+LC877		lda #8				; do 8 iterations of this scheme
+		sta soundrepeat			; set iteration counter
+LC87B		bsr sndseqnext			; calculate new delay factor
+		clra				; lose MSB
+		lsrb				; double delay factor
+		bne LC882			; brif not zero
+		incb				; make sure don't do a massive delay
+LC882		tfr d,x				; put delay into correct register
+		bsr LC82E			; do a sliding tone
+		dec soundrepeat			; have we done enough yet?
+		bne LC87B			; brif not
+; sound 22 - sound made just as a wizard fades out
+; start with a short burst sliding from 405Hz to 162Hz, frequency shifting every half wave
+; then, delay 36.6ms
+; then, do a longer burst sliding from 622Hz to 162Hz, frequency shifting every two waves
+; both bursts have semi-random amplitude derived from the sequence generator.
+; For this sound, the sequence will be spun 616 times.
+LC88A		ldu #LDBD2			; point to tone generator info
+		bsr LC893			; process first pair
+		bsr LC8BA			; delay for 36.6ms
+		leau 4,u			; move to next pair of values
+LC893		ldx ,u				; get delay value (frequency)
+LC895		ldy 2,u				; get wave count for each frequency
+LC898		bsr setdacseqdel		; set the dac for the first half-wave
+		leay -1,y			; are we done yet?
+		bne LC898			; brif not
+		leax 2,x			; lengthen delay slightly (reduce frequency)
+		cmpx #$150			; are we at the minimum frequency (163Hz)?
+		bne LC895			; brif not - get wave count again and keep going
+		rts				; return to caller
+; sound 16 - sword
+; Uses random amplitude on an ascending volumn scale (roughly 510 iterations)
+LC8A6		jsr LC931			;* set for ascending volume from 0 to $ff with a step of 0.5
+		fcb $80				;*
+LC8AA		bsr LC922			; apply step and program DAC
+		bcs LC8B2			; brif counter wrapped
+		bsr setdac			; set the DAC
+		bra LC8AA			; keep looping
+; sound 17 - torch 
+; Uses a random amplitude on a descending volume scale (roughly 405 iterations)
+LC8B2		jsr LC92E			;* set for descending volume from $ffff with a step of 0.625
+		fcb $a0				;*
+LC8B6		bsr LC926			; apply step, multiplier, and set the dac - will return to our caller when done
+		bra LC8B6			; go apply another step
+LC8BA		ldx #$1000			; delay factor for 36.6ms
+; This routine counts X down nondestructively. It takes 16+8n cycles where
+; n is the value in X.
+snddelay	pshs x				; (7~) save delay counter
+snddelay000	leax -1,x			; (5~) has timer expired?
+		bne snddelay000			; (3~) brif not
 LC8C3		puls x,pc			; (9~) restore delay counter and return
-LC8C5		ldb soundvol			; (5~) fetch volume multiplier for sound
+; This routine programs the DAC with the intensity in A adjusted by the sound volume.
+; This routine takes 27 cycles.
+setdac		ldb soundvol			; (5~) fetch volume multiplier for sound
 		mul				; (11~) multiply it by the value we're trying to set
 		anda #$fc			; (2~) lose the non-DAC bits
 		sta PIA1			; (5~) set DAC
 		rts				; (5~)
-LC8CE		ldd V256
-		lslb
-		rola
-		lslb
-		rola
-		addd V256
-		incb
-		std V256
-		rts
-; sound 15
-LC8DA		bsr LC915
+; This routine is a sequence generator with a period of 32768. soundseqseed is never initialized except 
+sndseqnext	ldd soundseqseed		; (5~) fetch current value
+		lslb				;* (2~) multiply by 4
+		rola				;* (2~) 
+		lslb				;* (2~)
+		rola				;* (2~)
+		addd soundseqseed		; (6~) add to previous value
+		incb				; (2~) bump lsb
+		std soundseqseed		; (5~) save new value
+		rts				; (5~) return to caller
+; sound 15 - shield
+; Run a dual wave with a low wave of 955Hz and a high wave of 3020Hz
+LC8DA		bsr sndrundualwave
 		fdb $6424
-; sound 7
-LC8DE		bsr LC915
+; sound 7 - shield knight
+; Run a dual wave with a low wave of 1670Hz and a high wave of 3195Hz
+LC8DE		bsr sndrundualwave
 		fdb $3212
-; sound 4
-LC8E2		bsr LC915
+; sound 4 - knight
+; Run a dual wave with a low wave of 580Hz and a high wave of 1575Hz
+LC8E2		bsr sndrundualwave
 		fdb $AF36
-; sound 19
-LC8E6		bsr LC915
+; sound 19 - attack hit against player
+; Run a dual wave with a low wave of 2660Hz and a high wave of 4300Hz
+LC8E6		bsr sndrundualwave
 		fdb $1909
-LC8EA		bsr LC92E
-		fcb $60
-LC8ED		ldx V263
-		ldy V265
-		clra
-LC8F3		leax -1,x
-		bne LC8FD
-		ldx V263
-		eora #$7f
-		bsr LC90A
-LC8FD		leay -1,y
-		bne LC8F3
-		ldy V265
-		eora #$80
-		bsr LC90A
-		bra LC8F3
-LC90A		sta V259
-		bsr LC97E
-		bls LC8C3			; skip the caller to this routine and return to its caller
-		bsr LC8C5
-		lda V259
-		rts
+; This routine runs essentially a dual tone. The "frequency" of the lower bits is determined by the value
+; in sndlowtonedel. The frequency of the high bit is determined by the delay in sndhitonedel. The two frequencies run
+; independently.
+LC8EA		bsr LC92E			;* set up for descending volume with a step of 0.375
+		fcb $60				;*
+LC8ED		ldx sndlowtonedel		; fetch low bits flip rate
+		ldy sndhitonedel		; fetch high bit flip rate
+		clra				; initialize both "waves" to low
+LC8F3		leax -1,x			; (5~) have we timed out on this level?
+		bne LC8FD			; (3~) brif not
+		ldx sndlowtonedel		; (5~) reset counter
+		eora #$7f			; (2~) flip all low bits of dac value
+		bsr LC90A			; (7~) apply step and scale - will return to our caller when things overflow (111~)
+LC8FD		leay -1,y			; (5~) have run through the other sequence
+		bne LC8F3			; (3~) brif not - start again
+		ldy sndhitonedel		; (6~) reset counter
+		eora #$80			; (2~) flip high bit of dac value
+		bsr LC90A			; (7~) apply step and scale - will return to our caller whent hings overflow (111~)
+		bra LC8F3			; (3~) go check things again
+LC90A		sta sndtemp			; (4~) save dac value
+		bsr LC97E			; (7~) go calculate step and multiplier (53~)
+		bls LC8C3			; (3~) skip the caller to this routine and return to its caller (PULS X,PC) if we wrapped
+		bsr setdac			; (7~) set the dac (28~)
+		lda sndtemp			; (4~) get back original dac value
+		rts				; (5~) return to caller
 ; this routine doesn't return to the caller but to the caller's caller
-LC915		ldx ,s++
-		ldb ,x+
-		clra
-		std V263
-		ldb ,x+
-		std V265
-		bra LC8EA
-LC922		bsr LC8CE
-		bra LC98D
-LC926		bsr LC8CE
-LC928		bsr LC97E
-		bls LC8C3			; skip the caller to this routine and return to its caller
-		bra LC8C5
-LC92E		ldx allones
+sndrundualwave	ldx ,s++			; fetch location of parameters
+		ldb ,x+				; fetch delay constant for low wave
+		clra				; zero extend
+		std sndlowtonedel		; save it
+		ldb ,x+				; fetch delay constant for high wave
+		std sndhitonedel		; save it
+		bra LC8EA			; go process sound
+LC922		bsr sndseqnext			; get a value from the sequence
+		bra LC98D			; apply step and multplier (ascending)
+LC926		bsr sndseqnext			; get value from sequence
+LC928		bsr LC97E			; apply step and multiplier (descending)
+		bls LC8C3			; skip the caller to this routine and return to its caller if we wrapped
+		bra setdac			; set the dac and return
+LC92E		ldx allones			; set initial base value to $ffff
+		fcb $10				; go set up the step value
+LC931		ldx zero			; set initial base value to $0000
+LC933		stx sndampmult			; save initial base multiplier
+		ldx ,s				; get return address
+		ldb ,x+				; fetch step value
+		clra				; zero extend
+		std sndampstep			; save step value
+		stx ,s				; save return address to be after step value
+		rts				; return to caller
+; sound 18 - attack hit against creature
+; This is a sort of noisy square wave with a rough frequency of 4360Hz
+LC93F		bsr LC92E			;* set up a countdown with step 0.375
+		fcb $60				;*
+LC942		jsr sndseqnext			; get a sequence value
+		lsra				; make it in the low half of the range
+		bsr LC928			; apply step and multiplier (descending) (will return to caller when overflow)
+		jsr sndseqnext			; get another sequence value
+		ora #$80			; force it high
+		bsr LC928			; apply the step and multiplier (descending) (will return to our caller when overflow)
+		bra LC942			; keep looping
+; These three are basically the same sound. However, the stronger creatures have longer sounds that take longer
+; to reach full volume, and thus longer to complete. The axe giant is roughly twice as long as the club giant and
+; the galdrog is roughly three times as long as the club giant.
+; sound 2 - club giant
+LC951		ldx #$300			; step value for club giant (3)
 		fcb $10
-LC931		ldx zero
-LC933		stx V25B
-		ldx ,s
-		ldb ,x+
-		clra
-		std V25D
-		stx ,s
-		rts
-; sound 18
-LC93F		bsr LC92E
-		fcb $60
-LC942		jsr LC8CE
-		lsra
-		bsr LC928
-		jsr LC8CE
-		ora #$80
-		bsr LC928
-		bra LC942
-; sound 2
-LC951		ldx #$300
-		fcb $10
-; sound 5
+; sound 5 - axe giant				; step value for axe giant (2)
 LC955		ldx #$200
 		fcb $10
-; sound 9
+; sound 9 - galdrog				; step value for galdrog (1)
 LC959		ldx #$100
-		stx V25D
-		clra
+		stx sndampstep			; save step value
+		clra				; starting value at 0 (count up)
 		clrb
-		std V25B
-LC962		bsr LC922
-		bcs LC971
-		jsr LC8C5
-		ldx #$f0
-		jsr LC8BD
-		bra LC962
-LC971		bsr LC92E
-		fcb $40
-LC974		bsr LC926
-		ldx #$60
-		jsr LC8BD
-		bra LC974
-LC97E		pshs a
-		ldd V25B
-		subd V25D
-LC984		pshs cc
-		std V25B
-		ldb 1,s
-		mul
-		puls cc,b,pc
-LC98D		pshs a
-		ldd V25B
-		addd V25D
-		bra LC984
+		std sndampmult			; set starting multiplier
+LC962		bsr LC922			; get a value from the sequence and apply multiplier
+		bcs LC971			; brif we overflowed - done
+		jsr setdac			; set the dac
+		ldx #$f0			; delay for roughly 200Hz
+		jsr snddelay			; go delay
+		bra LC962			; go run another half wave
+LC971		bsr LC92E			;* set up for a count down with a step of 0.25
+		fcb $40				;*
+LC974		bsr LC926			; get a sequence value and apply the step (descending), will return to our caller when done
+		ldx #$60			; get delay roughly equal to  1050Hz
+		jsr snddelay			; do the delay
+		bra LC974			; go do another half wave
+LC97E		pshs a				; (6~) save sequence value
+		ldd sndampmult			; (5~) get mulitplier base
+		subd sndampstep			; (6~) apply step value
+LC984		pshs cc				; (6~) save result of subtraction
+		std sndampmult			; (5~) save new multiplier base
+		ldb 1,s				; (5~) get back dac value
+		mul				; (11~) apply multiplier - use MSB in A
+		puls cc,b,pc			; (9~) restore registers and return
+LC98D		pshs a				; save sequence value
+		ldd sndampmult			; get multiplier base
+		addd sndampstep			; add step value
+		bra LC984			; go deal with multiplier
 ; this is the swi routine offset table - each byte is the difference between the entry point
 ; of the previous routine and itself
 LC995		fcb 0				; first routine has nothing before it
@@ -4039,8 +4095,8 @@
 		fcb $00,$b0,$f8,$f8,$f0,$e0,$40	; char code 35 - right part of expanded heart
 
 ; These two entries are related to sound generation.
-LDBD2		fcb $00,$80,$00,$01,$00,$50,$00,$04
-LDBDA		fcb $00,$50,$00,$05
+LDBD2		fcb $00,$80,$00,$01,$00,$50,$00,$04	; for the "wizard fade out" sound and the walk into wall sound
+LDBDA		fcb $00,$50,$00,$05			; for the create death sound
 
 ; This table is for rendering walls in specific directions. There is one entry each
 ; for left, right, and forward. Each entry has four pointers to graphics, for no door,