/
fxsample.c
152 lines (130 loc) · 2.2 KB
/
fxsample.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "fxsample.h"
void initPSG(void *psginit) __naked __z88dk_fastcall {
(void) psginit;
/* ********************************************************************
Inits Psg
*/
__asm
; Init PSG
ld bc,#0x0b7f
otir
ret
__endasm;
}
void PlaySample (void *sample) __naked __z88dk_fastcall {
(void) sample;
/* ********************************************************************
Plays a Sample
*/
__asm
;Replayer core to play RLE encoded 8.000kHz samples generated by pcmenc
;
; pcmenc should use the following command line arguments:
;
; pcmenc -rto 1 -dt1 12 -dt2 12 -dt3 423 file.wav
;
; and optionally -r to split sample into blocks for rom replayer
;
; There are three channel updates per underlying sample.
; We emit three channel updates together, as fast as possible, looping
; every 447 cycles, to match an underlying sample at 8008Hz
; (3579545/447=8007.9).
; Work costs 309 cycles so we waste 139.
PLAY_SAMPLE:
;disable interrupts
di
;save ix
push ix
ld de,#0x0000
ld bc,#0x0000
ld a, (hl)
inc hl
LDIXLA
ld a, (hl)
inc hl
LDIXHA
PsgLoop:
; Calculate channel A volume
ld a,b ; 4
sub #0x10 ; 7
jr nc,PsgWaitA ; 7/12
ld a,(hl) ; 7
inc hl ; 6
ld b,a ; 4
and #0x0f ; 7
or #0x90 ; 7
LDIYHA ; 8 -> 57
PsgDoneA:
; Calculate channel B volume
ld a,d ; 4
sub #0x10 ; 7
jr nc,PsgWaitB ; 7/12
ld a,(hl) ; 7
inc hl ; 6
ld d,a ; 4
and #0x0f ; 7
or #0xb0 ; 7
LDIYLA ; 8 -> 57
PsgDoneB:
; Calculate channel C volume
ld a,e ; 4
sub #0x10 ; 7
jr nc,PsgWaitC ; 7/12
ld a,(hl) ; 7
inc hl ; 6
ld e,a ; 4
and #0x0f ; 7
or #0xd0 ; 7
ld c,a ; 4 -> 53
PsgDoneC:
; Output channels
push de ; 11
LDDIYH ; 8
LDEIYL ; 8
ld a,c ; 4
push bc ; 11
ld c,#0x7f ; 7 -> 49
out (c),d ; 12
out (c),e ; 12
out (c),a ; 12
pop bc ; 10
pop de ; 10 -> 66
; Waste cycles
call Delay
; Decrement length and return if zero
dec ix ; 10
LDAIXH ; 8
ORIXL ; 8
jp nz,PsgLoop ; 10 -> 36
;restore ix
pop ix
;enable interrupts
ei
ret
PsgWaitA:
ld b,a ; 4
ld a,i ; 9
ld a,i ; 9
jr PsgDoneA ; 12 -> 34
PsgWaitB:
ld d,a ; 4
ld a,i ; 9
ld a,i ; 9
jr PsgDoneB ; 12 -> 34
PsgWaitC:
ld e,a ; 4
and #0x0 ; 7
and #0x0 ; 7
jr PsgDoneC ; 12 -> 30
Delay:
; call Delay 17
push bc ; 11
ld b,#0x6 ; 7
inner_loop: djnz inner_loop ; 13*5+8
pop bc ; 10
in a,(#0x7f) ; 11
ret ; 10
; ---
; 139
__endasm;
}