mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-02-09 01:31:14 +00:00
509 lines
14 KiB
ArmAsm
509 lines
14 KiB
ArmAsm
|
|
; This File: PUMPSND.S
|
|
; Author: Glyn H. Anderson; modified by Duncan Blanchard
|
|
; Created: 10-Nov-87 12:53
|
|
; Last Edit: 23-Nov-87 14:13; 23-Feb-88
|
|
|
|
; register conventions: in interrupt code, must preserve everything,
|
|
; elsewhere, preserve all except a0/d0
|
|
|
|
; is there any way to determine system clock speed at runtime? The "system
|
|
; timer calibration" global, _timr_ms, seems to be defined uselessly.
|
|
|
|
CLKFRQ equ 8000000 ;current ST clock freq (8 MHz)
|
|
GEMDOS equ 1 ;trap number
|
|
XBIOS equ 14
|
|
conterm equ $484 ;console attribute bits (lowmem global)
|
|
|
|
GISelect equ $FFFF8800 ;GI sound chip register select
|
|
GIRead equ GISelect ;GI sound chip register read
|
|
GIWrite equ GISelect+2 ;GI sound chip register write
|
|
|
|
*-----------------------
|
|
* globals
|
|
*-----------------------
|
|
|
|
bss
|
|
|
|
i_samp ds.l 1 ;address of sound samples
|
|
i_reps ds.w 1 ;repeat count
|
|
i_p ds.l 1 ;pointer to next sample
|
|
i_p2 ds.l 1 ;pointer to last sample (+1)
|
|
i_done ds.w 1 ;end-of-sound flag
|
|
|
|
oldSSP ds.l 1 ;saved supervisor stack pointer
|
|
oldSR ds.w 1 ;saved status register
|
|
oldct ds.b 1 ;saved keyclick/bell settings
|
|
|
|
*-----------------------
|
|
* pump_sound
|
|
*-----------------------
|
|
|
|
text
|
|
xdef pump_sound
|
|
|
|
pump_sound
|
|
move.l 4(a7),a0 ;get pointer to data buffer
|
|
move.w 8+2(a7),d0 ;get caller's repeat count
|
|
bsr ps_init
|
|
|
|
psndx1 move.w #$FF,-(sp)
|
|
move.w #6,-(sp) ;periodically check for a key
|
|
trap #GEMDOS
|
|
addq.l #4,sp ;flush stack
|
|
cmpi.b #$51,d0 ;'Q' to abort
|
|
beq.s psndx3
|
|
|
|
move.w #500,d0 ;5000-tick loop
|
|
psndx2 dbf d0,psndx2
|
|
tst.w i_done ;busy-wait for now ...
|
|
beq psndx1
|
|
|
|
psndx3 bsr ps_cleanup
|
|
rts ;from pump_sound
|
|
|
|
*-----------------------
|
|
* super
|
|
*-----------------------
|
|
|
|
; if d0 is nonzero enter super mode, else exit super mode
|
|
|
|
super tst.w d0
|
|
beq.s sprx1
|
|
|
|
clr.l -(sp)
|
|
move.w #$20,-(sp) ;Super is function $20
|
|
trap #GEMDOS
|
|
addq.l #6,sp ;flush (system?) stack
|
|
move.l d0,oldSSP ;save user SP
|
|
bra.s sprx2
|
|
|
|
sprx1 move.l oldSSP,-(sp) ;user SP
|
|
move.w #$20,-(sp)
|
|
trap #GEMDOS
|
|
addq.l #6,sp ;flush (user) stack
|
|
sprx2 rts
|
|
|
|
*-----------------------
|
|
* ps_init
|
|
*-----------------------
|
|
|
|
; setup for sound; a0 -> buffer, d0.w = reps
|
|
ps_init
|
|
move.l a0,i_samp ;store
|
|
*** clr.w d0
|
|
*** move.b 2(a0),d0 ;get data's repeat count (byte)
|
|
move.w d0,i_reps ;store
|
|
|
|
; enter Super mode, disable keyclick & bell (anything else?)
|
|
|
|
moveq #1,d0
|
|
bsr super
|
|
|
|
move.b conterm,d0
|
|
move.b d0,oldct ;save current settings
|
|
andi.b #$FA,d0
|
|
move.b d0,conterm ;disable os sounds
|
|
|
|
; disable interrupts and atomically adjust Mixer control bits
|
|
; (don't disturb I/O control bits)
|
|
|
|
move sr,d0 ;get status reg
|
|
move.w d0,oldSR
|
|
or.w #$0700,d0 ;disable interrupts
|
|
move d0,sr
|
|
|
|
move.l #GISelect,a0
|
|
move.b #$07,(a0) ;request mixer controls
|
|
move.b (a0),d0 ;get controls
|
|
ori.b #$3F,d0 ;disable all noise and tones
|
|
move.b d0,2(a0) ;set controls
|
|
|
|
; restore normal interrupts & user mode
|
|
|
|
move oldSR,sr
|
|
clr.w d0
|
|
bsr super
|
|
|
|
; install our sound interrupt vector
|
|
; We use 68901 timer A in divide-by-4 mode, which maximizes the playback
|
|
; accuracy at high sample rates (within 1 percent at 20 KHz). It also limits
|
|
; the lowest frequency we can handle to 7.6 KHz. If lower is needed we
|
|
; could easily add a second timer mode.
|
|
|
|
bsr rep_init ;set up interrupt vars
|
|
clr.w i_done ;reset flag
|
|
|
|
move.l #CLKFRQ,d0 ;timer clock freq (same as cpu?)
|
|
divu 4(a0),d0 ;over sample freq -> ticks per sample
|
|
lsr.w #2,d0 ;countdown using timer /4 mode
|
|
cmpi.w #$FF,d0 ;too slow?
|
|
ble.s psix1
|
|
move.w #$FF,d0 ;yes, clip to slowest
|
|
|
|
psix1 pea ps_loop ;interrupt handler
|
|
move.w d0,-(sp) ;count
|
|
move.w #$01,-(sp) ;control mode
|
|
clr.w -(sp) ;register A
|
|
move.w #$1F,-(sp) ;xbtimer call
|
|
trap #XBIOS ; <-- interrupts begin here
|
|
adda.w #12,sp ;flush stack
|
|
|
|
rts
|
|
|
|
*-----------------------
|
|
* ps_cleanup
|
|
*-----------------------
|
|
|
|
ps_cleanup
|
|
|
|
; un-install our interrupt
|
|
|
|
clr.l -(sp) ;interrupt handler
|
|
clr.w -(sp) ;count
|
|
move.w #$00,-(sp) ;control mode
|
|
clr.w -(sp) ;register A
|
|
move.w #$1F,-(sp) ;xbtimer call
|
|
trap #XBIOS ; <-- interrupts stop here
|
|
adda.w #12,sp ;flush stack
|
|
|
|
; restore keyclick and bell settings
|
|
|
|
moveq #1,d0 ;must be in Super mode
|
|
bsr super
|
|
move.b oldct,d0 ;get saved settings
|
|
move.b d0,conterm
|
|
clr.w d0
|
|
bsr super
|
|
rts
|
|
|
|
*-----------------------
|
|
* rep_init
|
|
*-----------------------
|
|
|
|
rep_init
|
|
move.l i_samp,a0 ;point to header
|
|
addq.l #8,a0 ;point to data length
|
|
moveq #0,d0
|
|
move.w (a0)+,d0 ;get it
|
|
move.l a0,i_p ;store pointer to start of data
|
|
add.l a0,d0
|
|
move.l d0,i_p2 ;store pointer to end of data (+1)
|
|
rts
|
|
|
|
*-----------------------
|
|
* ps_loop
|
|
*-----------------------
|
|
|
|
; interrupt entry point -- output the next sample
|
|
|
|
; Each pass through the critical section uses 288 ticks, plus interrupt
|
|
; overhead of 44 ticks, so an 18k sample rate (one every 434 ticks at 8 MHz)
|
|
; consumes 76 percent of total cpu time.
|
|
|
|
ps_loop
|
|
movem.l d0/a0-a1,-(sp) ;[38] ;registers used
|
|
move.l i_p,a0 ;[16] [+4?] ;pointer to next sample
|
|
cmpa.l i_p2,a0 ;[18] [+4?] ;end of cycle?
|
|
beq.s pslx3 ;[ 8] [10 tkn] ;yes ;[[ 80]]
|
|
|
|
pslx1 move.b (a0)+,d0 ; [8] ;get it
|
|
move.l a0,i_p ;[16] [+4?] ;update pointer
|
|
|
|
lea volmap(pc),a1 ; [8] ;address of conversion table
|
|
ext.w d0 ; [4] ;signed byte
|
|
adda.w d0,a1 ; [8]
|
|
add.w d0,d0 ; [4]
|
|
adda.w d0,a1 ; [8] ;offset x3 ;[[ 56]]
|
|
|
|
; update volume on each channel (as simultaneously as possible)
|
|
|
|
move.l #GISelect,a0 ;[12]
|
|
move.b #8,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write A vol
|
|
move.b #9,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write B vol
|
|
move.b #10,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write C vol ;[[ 96]]
|
|
|
|
pslx2 movem.l (sp)+,d0/a0-a1 ;[36] ;restore regs
|
|
rte ;[20] ;return from exception ;[[ 56]]
|
|
|
|
; handle end of cycle. The longest path through this section shouldn't be
|
|
; allowed to exceed the length of the critical path above by very much, since
|
|
; the timing may be tight.
|
|
|
|
pslx3 tst.w i_done ;been here before?
|
|
bne.s pslx2 ;just waiting for user to disable ints
|
|
|
|
subq.w #1,i_reps ;any more reps?
|
|
beq.s pslx4 ;no
|
|
bsr rep_init ;yes, set up next cycle
|
|
bra.s pslx2 ;but wait until next int to start it
|
|
|
|
pslx4 move.w #1,i_done ;finished, raise flag
|
|
bra.s pslx2
|
|
|
|
*-----------------------
|
|
* volmap
|
|
*-----------------------
|
|
|
|
text ; keep read-only data in code seg for quick access
|
|
|
|
; This table maps signed bytes (-128..127) into amplitude inputs for the
|
|
; sound chip. Each digit is the 4-bit amplitude for one channel.
|
|
; In the Atari ST the three channels are not weighted equally; the values
|
|
; in the table were determined empirically.
|
|
|
|
; the table's entry point is in the middle, corresponding to signed '0'
|
|
|
|
dc.b $01,$1,$1,$01,$1,$2,$01,$1,$3,$00,$3,$3 ;4 groups per line
|
|
dc.b $01,$1,$4,$01,$2,$4,$01,$4,$2,$01,$4,$3
|
|
dc.b $01,$5,$2,$03,$3,$4,$04,$3,$3,$05,$3,$2
|
|
dc.b $05,$3,$3,$05,$4,$2,$05,$3,$4,$03,$6,$2
|
|
dc.b $03,$6,$3,$03,$4,$6,$03,$6,$4,$03,$5,$6
|
|
dc.b $04,$6,$4,$05,$6,$3,$04,$6,$5,$04,$7,$3
|
|
dc.b $05,$7,$2,$05,$7,$3,$04,$7,$5,$05,$7,$4
|
|
dc.b $05,$6,$6,$05,$7,$5,$04,$7,$6,$03,$7,$7
|
|
dc.b $05,$7,$6,$05,$8,$3,$04,$8,$5,$03,$8,$6
|
|
dc.b $07,$6,$6,$07,$7,$5,$07,$8,$0,$05,$9,$0
|
|
dc.b $05,$9,$1,$05,$9,$2,$05,$9,$3,$04,$9,$5
|
|
dc.b $06,$9,$1,$06,$9,$2,$06,$9,$3,$07,$9,$0
|
|
dc.b $08,$8,$2,$08,$8,$3,$09,$6,$5,$09,$0,$8
|
|
dc.b $09,$7,$4,$09,$6,$6,$09,$7,$5,$09,$8,$0
|
|
dc.b $08,$9,$1,$08,$9,$2,$08,$9,$3,$08,$8,$7
|
|
dc.b $07,$9,$7,$08,$9,$5,$06,$A,$3,$09,$6,$8
|
|
dc.b $09,$4,$9,$08,$7,$9,$09,$5,$9,$09,$9,$3
|
|
dc.b $09,$9,$4,$0A,$6,$6,$0A,$7,$5,$0A,$3,$8
|
|
dc.b $08,$A,$1,$08,$A,$2,$04,$B,$2,$04,$B,$3
|
|
dc.b $03,$B,$5,$03,$A,$9,$02,$B,$6,$03,$B,$6
|
|
dc.b $06,$B,$2,$06,$B,$3,$06,$B,$4,$07,$B,$1
|
|
dc.b $07,$B,$2,$07,$B,$3,$07,$B,$4,$07,$B,$5
|
|
dc.b $07,$A,$9,$02,$A,$A,$03,$A,$A,$09,$2,$B
|
|
dc.b $09,$3,$B,$08,$9,$A,$08,$7,$B,$05,$9,$B
|
|
dc.b $03,$3,$C,$03,$4,$C,$05,$2,$C,$05,$3,$C
|
|
dc.b $06,$1,$C,$07,$9,$B,$06,$3,$C,$04,$6,$C
|
|
dc.b $06,$4,$C,$07,$2,$C,$07,$3,$C,$07,$4,$C
|
|
dc.b $07,$5,$C,$05,$B,$A,$08,$B,$9,$0A,$6,$B
|
|
dc.b $09,$B,$8,$09,$A,$A,$09,$9,$B,$08,$5,$C
|
|
dc.b $06,$C,$5,$07,$C,$3,$05,$C,$7,$03,$C,$8
|
|
dc.b $03,$B,$B,$08,$7,$C,$04,$B,$B,$05,$C,$8
|
|
dc.b $05,$B,$B,$06,$9,$C,$06,$C,$8,$06,$B,$B
|
|
volmap
|
|
dc.b $0A,$9,$B,$09,$B,$A,$0B,$9,$A,$0B,$B,$2
|
|
dc.b $0B,$A,$9,$09,$C,$4,$09,$C,$5,$0A,$4,$C
|
|
dc.b $0A,$5,$C,$0B,$8,$B,$0C,$1,$A,$0C,$2,$A
|
|
dc.b $0C,$3,$A,$0C,$4,$A,$0C,$5,$A,$0C,$8,$9
|
|
dc.b $0C,$9,$8,$0C,$6,$A,$0C,$A,$1,$0C,$A,$3
|
|
dc.b $0C,$A,$5,$0C,$9,$9,$0C,$A,$6,$0C,$1,$B
|
|
dc.b $0C,$A,$7,$0D,$2,$5,$0D,$3,$5,$0D,$5,$3
|
|
dc.b $0D,$5,$4,$0D,$5,$5,$0D,$6,$3,$0D,$6,$4
|
|
dc.b $0D,$6,$5,$0D,$7,$2,$0D,$6,$6,$0D,$7,$4
|
|
dc.b $0D,$7,$5,$0D,$7,$6,$0D,$8,$0,$0D,$7,$7
|
|
dc.b $0D,$6,$8,$0D,$8,$5,$0D,$8,$6,$0D,$8,$7
|
|
dc.b $0D,$9,$0,$0D,$9,$2,$0D,$9,$4,$0D,$9,$5
|
|
dc.b $0D,$9,$6,$0D,$3,$A,$0D,$4,$A,$0D,$5,$A
|
|
dc.b $0D,$6,$A,$0B,$3,$D,$0B,$4,$D,$0B,$5,$D
|
|
dc.b $0D,$A,$1,$0D,$A,$3,$0D,$A,$5,$0D,$A,$6
|
|
dc.b $0D,$A,$7,$0D,$4,$B,$0D,$5,$B,$0D,$A,$8
|
|
dc.b $0D,$6,$B,$0D,$7,$B,$0D,$A,$9,$0D,$8,$B
|
|
dc.b $0D,$B,$3,$0D,$B,$5,$0D,$B,$6,$0D,$B,$7
|
|
dc.b $0D,$9,$B,$0D,$B,$8,$0B,$A,$D,$0C,$0,$D
|
|
dc.b $0C,$2,$D,$0C,$4,$D,$0C,$5,$D,$0D,$0,$C
|
|
dc.b $0D,$2,$C,$0D,$3,$C,$0D,$4,$C,$0D,$5,$C
|
|
dc.b $0D,$6,$C,$0D,$B,$A,$0D,$7,$C,$0D,$8,$C
|
|
dc.b $0C,$9,$D,$0D,$9,$C,$0D,$B,$B,$0C,$D,$3
|
|
dc.b $0C,$D,$6,$0C,$D,$7,$0D,$C,$7,$0C,$D,$8
|
|
dc.b $0D,$C,$8,$0A,$D,$C,$0A,$1,$E,$0A,$3,$E
|
|
dc.b $0A,$5,$E,$0A,$6,$E,$0A,$7,$E,$0C,$D,$A
|
|
dc.b $06,$D,$D,$07,$D,$D,$08,$E,$6,$0A,$9,$E
|
|
dc.b $08,$D,$D,$0C,$D,$B,$0E,$7,$8,$09,$D,$D
|
|
dc.b $0A,$7,$E,$0C,$D,$A,$0D,$C,$A,$0B,$C,$D
|
|
dc.b $0C,$B,$D,$05,$D,$D,$07,$E,$8,$0B,$D,$C
|
|
dc.b $0D,$5,$D,$0E,$4,$8,$0D,$6,$D,$0E,$7,$6
|
|
dc.b $0D,$7,$D,$0D,$C,$B,$0D,$8,$D,$09,$D,$D
|
|
|
|
end
|
|
;of assembly
|
|
text
|
|
|
|
*-----------------------
|
|
* DEAD CODE
|
|
*-----------------------
|
|
|
|
LOOPLEN equ 220 ;was 286, 214, 238-5
|
|
WASTELEN equ 10 ;length of waste loop
|
|
LLEN2 equ 106
|
|
SYNCCNT equ 100 ;resync every n samples
|
|
|
|
; from setup ...
|
|
move.l #CLKFRQ,d0 ;ST clock freq
|
|
divu 4(a0),d0 ;over sample freq -> ticks per sample
|
|
sub.w #LOOPLEN,d0 ;take out loop's length
|
|
bpl.s psix1 ;branch if we've got time to waste...
|
|
moveq #0,d0 ;else don't waste any
|
|
psix1 and.l #$0000FFFF,d0 ;clear upper bits
|
|
divu #WASTELEN,d0 ;length of waste loop
|
|
move.w d0,i_waste ;save waste count
|
|
|
|
sub.w #LLEN2/10,d0 ;reduced waste after sync section
|
|
bpl.s psx2
|
|
moveq #0,d0
|
|
psx2 move.w d0,w2
|
|
clr.w sync ;resync first time thru
|
|
|
|
; synchronize with beginning of a new square wave
|
|
; For smoother sq wave (and reduced cpu load), do this only every nth pass
|
|
|
|
subq.w #1,sync ;[16] ;time to resync?
|
|
bgt.s plx2 ;[10] ;no [8 if not taken] ;[[ 26]]
|
|
move.w #SYNCCNT,sync ;[16]
|
|
move.w w2,w_use ;[20] ;adjust waste val
|
|
|
|
; move.b #0,(a2) ;chan A period = longest poss
|
|
; move.b #$FF,(a3) ;(ignore 8 ls period bits)
|
|
move.b #1,(a2) ;[12]
|
|
move.b #$0F,(a3) ;[12]
|
|
; move.b #2,(a2) ;chan B period = longest poss
|
|
; move.b #$FF,(a3)
|
|
move.b #3,(a2) ;[12]
|
|
move.b #$0F,(a3) ;[12]
|
|
; move.b #4,(a2) ;chan C period = longest poss
|
|
; move.b #$FF,(a3)
|
|
move.b #5,(a2) ;[12]
|
|
move.b #$0F,(a3) ;[12] ;72+36-2 ;[[106]]
|
|
|
|
; fetch and unpack 3 amplitude values
|
|
|
|
clr.w d0
|
|
move.b (a0)+,d0 ; [8] ;get sample
|
|
eor.b #$80,d0 ; [8] ;offset the sample
|
|
lsl.w #1,d0 ; [8] ;index into WORDs
|
|
|
|
move.w 0(a1,d0.w),d0 ;[14] ;get 12-bit version
|
|
move.w d0,d1 ; [4] ;copy it
|
|
move.w d0,d2 ; [4] ;twice
|
|
lsr.w #8,d0 ;[22] ;get A
|
|
lsr.b #4,d1 ;[14] ;get B
|
|
and.b #$0F,d2 ; [8] ;get C [66]
|
|
|
|
;; move.w 0(a1,d0.w),d2 ;[14] ;get 12-bit version
|
|
;; move.w d2,d1 ; [4]
|
|
;; and.b #$0F,d2 ; [8] ;extract C
|
|
;; lsr.b #4,d1 ;[14] ;shift B into position
|
|
;; move.w d1,d0 ; [4]
|
|
;; and.b #$0F,d1 ; [8] ;extract B
|
|
;; lsr.b #4,d0 ;[14] ;shift A into position [66]
|
|
|
|
; (after pump_next)
|
|
|
|
move.b #$07,GISelect ;done -- disable all tone and noise [dbb]
|
|
move.b GIRead,d0
|
|
or.b #$3F,d0
|
|
move.b d0,GIWrite
|
|
|
|
end
|
|
|
|
;;; I. alternate critical loop; assumes modified word-packing in table
|
|
|
|
ps_loop
|
|
move.w d0,-(sp) ;[ 8]
|
|
move.l a0,-(sp) ;[14]
|
|
subq.w #1,i_n ;[16] [20?] ;reached end of cycle?
|
|
beq.s pslx3 ;[ 8] [10 tk] ;yes ;[[ 46]]
|
|
|
|
pslx1 move.l i_p,a0 ;[16] [?] ;pointer to next sample
|
|
move.b (a0)+,d0 ; [8] ;get it
|
|
move.l a0,i_p ;[16] [?] ;update pointer
|
|
|
|
lea volmap(pc),a0 ; [8] ;address of conversion table
|
|
ext.w d0 ; [4] ;signed byte
|
|
add.w d0,d0 ; [4]
|
|
move.w 0(a0,d0.w),d0 ;[14] ;[[ 70]]
|
|
|
|
; update volume on each channel (as simultaneously as possible)
|
|
|
|
move.l #GISelect,a0 ;[12]
|
|
move.b #8,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write A vol
|
|
lsr.w #5,d0 ;[16] ;position next nybble, fifth bit zeroed
|
|
move.b #9,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write B vol
|
|
lsr.w #5,d0 ;[16]
|
|
move.b #10,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write C vol ;[[116]]
|
|
|
|
pslx2 move.l (sp)+,a0 ;[12] ;exit
|
|
move.w (sp)+,d0 ;[ 8]
|
|
rts ;[16] ;total 268 (was 282) ;[[ 36]]
|
|
|
|
|
|
;;; II. modified crit, interrupt vars located directly under voltab
|
|
|
|
ps_loop
|
|
movem.l d0/a0-a1,-(sp) ;[38]
|
|
lea volmap,a1 ;[12] ;conversion table & vars
|
|
move.l -4(a1),a0 ;[16] ;pointer to next sample
|
|
cmp.w -6(a1),a0 ;[10] ;reached end of cycle?
|
|
beq.s pslx3 ;[ 8] [10 tk] ;yes ;[[ 84]]
|
|
|
|
pslx1 clr.w d0 ; [4] ;unsigned byte
|
|
move.b (a0)+,d0 ; [8] ;get it
|
|
move.l a0,-4(a1) ;[16] ;update pointer
|
|
|
|
adda.w d0,a1 ; [8]
|
|
add.w d0,d0 ; [4]
|
|
adda.w d0,a1 ; [8] ;offset x3 ;[[ 44]]
|
|
|
|
; update volume on each channel (as simultaneously as possible)
|
|
|
|
move.l #GISelect,a0 ;[12]
|
|
move.b #8,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write A vol
|
|
move.b #9,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write B vol
|
|
move.b #10,(a0) ;[12]
|
|
move.b (a1)+,2(a0) ;[16] ;write C vol ;[[ 96]]
|
|
|
|
pslx2 movem.l (sp)+,d0/a0-a1 ;[36] ;exit
|
|
rts ;[16] ;total 276 (282) ;[[ 52]]
|
|
|
|
|
|
;;; III. alternate critical loop; assumes modified word-packing in table
|
|
;;; AND interrupt vars located directly under voltab
|
|
|
|
ps_loop
|
|
move.w d0,-(sp) ;[ 8]
|
|
move.l a0,-(sp) ;[14]
|
|
|
|
lea volmap-4,a0 ;[12] ;conversion table & vars
|
|
move.l (a0),d0 ;[12] ;pointer to next sample
|
|
cmp.w -2(a0),d0 ;[10] ;reached end of cycle?
|
|
beq.s pslx3 ;[ 8] [10 tk] ;yes ;[[ 84]]
|
|
|
|
pslx1 move.l i_p,a0 ;[16] [?] ;pointer to next sample
|
|
move.b (a0)+,d0 ; [8] ;get it
|
|
move.l a0,i_p ;[16] [?] ;update pointer
|
|
|
|
lea volmap(pc),a0 ; [8] ;address of conversion table
|
|
ext.w d0 ; [4] ;signed byte
|
|
add.w d0,d0 ; [4]
|
|
move.w 0(a0,d0.w),d0 ;[14] ;[[ 70]]
|
|
|
|
; update volume on each channel (as simultaneously as possible)
|
|
|
|
move.l #GISelect,a0 ;[12]
|
|
move.b #8,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write A vol
|
|
lsr.w #5,d0 ;[16] ;position next nybble, fifth bit zeroed
|
|
move.b #9,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write B vol
|
|
lsr.w #5,d0 ;[16]
|
|
move.b #10,(a0) ;[12]
|
|
move.b d0,2(a0) ;[12] ;write C vol ;[[116]]
|
|
|
|
pslx2 move.l (sp)+,a0 ;[12] ;exit
|
|
move.w (sp)+,d0 ;[ 8]
|
|
rts ;[16] ;total 268 (was 282) ;[[ 36]]
|
|
|