summaryrefslogtreecommitdiff
path: root/apps/codecs/libasap/apokeysnd.c
diff options
context:
space:
mode:
authorDominik Wenger <domonoky@googlemail.com>2010-02-04 17:31:10 +0000
committerDominik Wenger <domonoky@googlemail.com>2010-02-04 17:31:10 +0000
commit35472fe7f1c7133fa4291dad36ae457a460f021c (patch)
treec84a0118c7c992a30d0cb42d1778ec9918184b1f /apps/codecs/libasap/apokeysnd.c
parentb1a6c9096dfde44249d0f4d8a929c63a89987623 (diff)
downloadrockbox-35472fe7f1c7133fa4291dad36ae457a460f021c.tar.gz
rockbox-35472fe7f1c7133fa4291dad36ae457a460f021c.zip
sync asap codec to ASAP 2.1
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24511 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libasap/apokeysnd.c')
-rw-r--r--apps/codecs/libasap/apokeysnd.c586
1 files changed, 323 insertions, 263 deletions
diff --git a/apps/codecs/libasap/apokeysnd.c b/apps/codecs/libasap/apokeysnd.c
index 1d48bc20d2..a461fa96da 100644
--- a/apps/codecs/libasap/apokeysnd.c
+++ b/apps/codecs/libasap/apokeysnd.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * apokeysnd.c - another POKEY sound emulator 2 * apokeysnd.c - another POKEY sound emulator
3 * 3 *
4 * Copyright (C) 2007-2008 Piotr Fusik 4 * Copyright (C) 2007-2009 Piotr Fusik
5 * 5 *
6 * This file is part of ASAP (Another Slight Atari Player), 6 * This file is part of ASAP (Another Slight Atari Player),
7 * see http://asap.sourceforge.net 7 * see http://asap.sourceforge.net
@@ -20,114 +20,109 @@
20 * along with ASAP; if not, write to the Free Software Foundation, Inc., 20 * along with ASAP; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */ 22 */
23#include "codeclib.h"
24#if !defined(JAVA) && !defined(CSHARP)
25#include <string.h>
26#endif
27 23
28#include "asap_internal.h" 24#include "asap_internal.h"
29 25
30#define memset ci->memset
31#define ULTRASOUND_CYCLES 112 26#define ULTRASOUND_CYCLES 112
32 27
33#define MUTE_FREQUENCY 1 28#define MUTE_FREQUENCY 1
34#define MUTE_INIT 2 29#define MUTE_INIT 2
35#define MUTE_USER 4 30#define MUTE_USER 4
36 31
37CONST_LOOKUP(byte, poly4_lookup) = 32CONST_ARRAY(byte, poly4_lookup)
38 { 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1 }; 33 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1
39CONST_LOOKUP(byte, poly5_lookup) = 34END_CONST_ARRAY;
40 { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 35CONST_ARRAY(byte, poly5_lookup)
41 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1 }; 36 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1,
37 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1
38END_CONST_ARRAY;
42 39
43FILE_FUNC void init_state(PokeyState PTR pst) 40PRIVATE FUNC(void, PokeySound_InitializeChip, (P(PokeyState PTR, pst)))
44{ 41{
45 PST audctl = 0; 42 pst _ audctl = 0;
46 PST init = FALSE; 43 pst _ init = FALSE;
47 PST poly_index = 15 * 31 * 131071; 44 pst _ poly_index = 15 * 31 * 131071;
48 PST div_cycles = 28; 45 pst _ div_cycles = 28;
49 PST mute1 = MUTE_FREQUENCY | MUTE_USER; 46 pst _ mute1 = MUTE_FREQUENCY | MUTE_USER;
50 PST mute2 = MUTE_FREQUENCY | MUTE_USER; 47 pst _ mute2 = MUTE_FREQUENCY | MUTE_USER;
51 PST mute3 = MUTE_FREQUENCY | MUTE_USER; 48 pst _ mute3 = MUTE_FREQUENCY | MUTE_USER;
52 PST mute4 = MUTE_FREQUENCY | MUTE_USER; 49 pst _ mute4 = MUTE_FREQUENCY | MUTE_USER;
53 PST audf1 = 0; 50 pst _ audf1 = 0;
54 PST audf2 = 0; 51 pst _ audf2 = 0;
55 PST audf3 = 0; 52 pst _ audf3 = 0;
56 PST audf4 = 0; 53 pst _ audf4 = 0;
57 PST audc1 = 0; 54 pst _ audc1 = 0;
58 PST audc2 = 0; 55 pst _ audc2 = 0;
59 PST audc3 = 0; 56 pst _ audc3 = 0;
60 PST audc4 = 0; 57 pst _ audc4 = 0;
61 PST tick_cycle1 = NEVER; 58 pst _ tick_cycle1 = NEVER;
62 PST tick_cycle2 = NEVER; 59 pst _ tick_cycle2 = NEVER;
63 PST tick_cycle3 = NEVER; 60 pst _ tick_cycle3 = NEVER;
64 PST tick_cycle4 = NEVER; 61 pst _ tick_cycle4 = NEVER;
65 PST period_cycles1 = 28; 62 pst _ period_cycles1 = 28;
66 PST period_cycles2 = 28; 63 pst _ period_cycles2 = 28;
67 PST period_cycles3 = 28; 64 pst _ period_cycles3 = 28;
68 PST period_cycles4 = 28; 65 pst _ period_cycles4 = 28;
69 PST reload_cycles1 = 28; 66 pst _ reload_cycles1 = 28;
70 PST reload_cycles3 = 28; 67 pst _ reload_cycles3 = 28;
71 PST out1 = 0; 68 pst _ out1 = 0;
72 PST out2 = 0; 69 pst _ out2 = 0;
73 PST out3 = 0; 70 pst _ out3 = 0;
74 PST out4 = 0; 71 pst _ out4 = 0;
75 PST delta1 = 0; 72 pst _ delta1 = 0;
76 PST delta2 = 0; 73 pst _ delta2 = 0;
77 PST delta3 = 0; 74 pst _ delta3 = 0;
78 PST delta4 = 0; 75 pst _ delta4 = 0;
79 PST skctl = 3; 76 pst _ skctl = 3;
80 ZERO_ARRAY(PST delta_buffer); 77 ZERO_ARRAY(pst _ delta_buffer);
81} 78}
82 79
83ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast) 80FUNC(void, PokeySound_Initialize, (P(ASAP_State PTR, ast)))
84{ 81{
85 int i; 82 V(int, i);
86 int reg; 83 V(int, reg);
87 reg = 0x1ff; 84 reg = 0x1ff;
88 for (i = 0; i < 511; i++) { 85 for (i = 0; i < 511; i++) {
89 reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1); 86 reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1);
90 AST poly9_lookup[i] = (byte) reg; 87 ast _ poly9_lookup[i] = TO_BYTE(reg);
91 } 88 }
92 reg = 0x1ffff; 89 reg = 0x1ffff;
93 for (i = 0; i < 16385; i++) { 90 for (i = 0; i < 16385; i++) {
94 reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8); 91 reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8);
95 AST poly17_lookup[i] = (byte) (reg >> 1); 92 ast _ poly17_lookup[i] = TO_BYTE(reg >> 1);
96 } 93 }
97 AST sample_offset = 0; 94 ast _ sample_offset = 0;
98 AST sample_index = 0; 95 ast _ sample_index = 0;
99 AST samples = 0; 96 ast _ samples = 0;
100 AST iir_acc_left = 0; 97 ast _ iir_acc_left = 0;
101 AST iir_acc_right = 0; 98 ast _ iir_acc_right = 0;
102 init_state(ADDRESSOF AST base_pokey); 99 PokeySound_InitializeChip(ADDRESSOF ast _ base_pokey);
103 init_state(ADDRESSOF AST extra_pokey); 100 PokeySound_InitializeChip(ADDRESSOF ast _ extra_pokey);
104} 101}
105 102
106#define CYCLE_TO_SAMPLE(cycle) (((cycle) * ASAP_SAMPLE_RATE + AST sample_offset) / ASAP_MAIN_CLOCK)
107
108#define DO_TICK(ch) \ 103#define DO_TICK(ch) \
109 if (PST init) { \ 104 if (pst _ init) { \
110 switch (PST audc##ch >> 4) { \ 105 switch (pst _ audc##ch >> 4) { \
111 case 10: \ 106 case 10: \
112 case 14: \ 107 case 14: \
113 PST out##ch ^= 1; \ 108 pst _ out##ch ^= 1; \
114 PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta##ch = -PST delta##ch; \ 109 pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta##ch = -pst _ delta##ch; \
115 break; \ 110 break; \
116 default: \ 111 default: \
117 break; \ 112 break; \
118 } \ 113 } \
119 } \ 114 } \
120 else { \ 115 else { \
121 int poly = cycle + PST poly_index - (ch - 1); \ 116 V(int, poly) = cycle + pst _ poly_index - (ch - 1); \
122 int newout = PST out##ch; \ 117 V(int, newout) = pst _ out##ch; \
123 switch (PST audc##ch >> 4) { \ 118 switch (pst _ audc##ch >> 4) { \
124 case 0: \ 119 case 0: \
125 if (poly5_lookup[poly % 31] != 0) { \ 120 if (poly5_lookup[poly % 31] != 0) { \
126 if ((PST audctl & 0x80) != 0) \ 121 if ((pst _ audctl & 0x80) != 0) \
127 newout = AST poly9_lookup[poly % 511] & 1; \ 122 newout = ast _ poly9_lookup[poly % 511] & 1; \
128 else { \ 123 else { \
129 poly %= 131071; \ 124 poly %= 131071; \
130 newout = (AST poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \ 125 newout = (ast _ poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
131 } \ 126 } \
132 } \ 127 } \
133 break; \ 128 break; \
@@ -140,11 +135,11 @@ ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast)
140 newout = poly4_lookup[poly % 15]; \ 135 newout = poly4_lookup[poly % 15]; \
141 break; \ 136 break; \
142 case 8: \ 137 case 8: \
143 if ((PST audctl & 0x80) != 0) \ 138 if ((pst _ audctl & 0x80) != 0) \
144 newout = AST poly9_lookup[poly % 511] & 1; \ 139 newout = ast _ poly9_lookup[poly % 511] & 1; \
145 else { \ 140 else { \
146 poly %= 131071; \ 141 poly %= 131071; \
147 newout = (AST poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \ 142 newout = (ast _ poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
148 } \ 143 } \
149 break; \ 144 break; \
150 case 10: \ 145 case 10: \
@@ -157,125 +152,141 @@ ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast)
157 default: \ 152 default: \
158 break; \ 153 break; \
159 } \ 154 } \
160 if (newout != PST out##ch) { \ 155 if (newout != pst _ out##ch) { \
161 PST out##ch = newout; \ 156 pst _ out##ch = newout; \
162 PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta##ch = -PST delta##ch; \ 157 pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta##ch = -pst _ delta##ch; \
163 } \ 158 } \
164 } 159 }
165 160
166FILE_FUNC void generate(ASAP_State PTR ast, PokeyState PTR pst, int current_cycle) 161/* Fills delta_buffer up to current_cycle basing on current AUDF/AUDC/AUDCTL values. */
162PRIVATE FUNC(void, PokeySound_GenerateUntilCycle, (P(ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, current_cycle)))
167{ 163{
168 for (;;) { 164 for (;;) {
169 int cycle = current_cycle; 165 V(int, cycle) = current_cycle;
170 if (cycle > PST tick_cycle1) 166 if (cycle > pst _ tick_cycle1)
171 cycle = PST tick_cycle1; 167 cycle = pst _ tick_cycle1;
172 if (cycle > PST tick_cycle2) 168 if (cycle > pst _ tick_cycle2)
173 cycle = PST tick_cycle2; 169 cycle = pst _ tick_cycle2;
174 if (cycle > PST tick_cycle3) 170 if (cycle > pst _ tick_cycle3)
175 cycle = PST tick_cycle3; 171 cycle = pst _ tick_cycle3;
176 if (cycle > PST tick_cycle4) 172 if (cycle > pst _ tick_cycle4)
177 cycle = PST tick_cycle4; 173 cycle = pst _ tick_cycle4;
178 if (cycle == current_cycle) 174 if (cycle == current_cycle)
179 break; 175 break;
180 if (cycle == PST tick_cycle3) { 176 if (cycle == pst _ tick_cycle3) {
181 PST tick_cycle3 += PST period_cycles3; 177 pst _ tick_cycle3 += pst _ period_cycles3;
182 if ((PST audctl & 4) != 0 && PST delta1 > 0 && PST mute1 == 0) 178 if ((pst _ audctl & 4) != 0 && pst _ delta1 > 0 && pst _ mute1 == 0)
183 PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta1 = -PST delta1; 179 pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta1 = -pst _ delta1;
184 DO_TICK(3); 180 DO_TICK(3);
185 } 181 }
186 if (cycle == PST tick_cycle4) { 182 if (cycle == pst _ tick_cycle4) {
187 PST tick_cycle4 += PST period_cycles4; 183 pst _ tick_cycle4 += pst _ period_cycles4;
188 if ((PST audctl & 8) != 0) 184 if ((pst _ audctl & 8) != 0)
189 PST tick_cycle3 = cycle + PST reload_cycles3; 185 pst _ tick_cycle3 = cycle + pst _ reload_cycles3;
190 if ((PST audctl & 2) != 0 && PST delta2 > 0 && PST mute2 == 0) 186 if ((pst _ audctl & 2) != 0 && pst _ delta2 > 0 && pst _ mute2 == 0)
191 PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta2 = -PST delta2; 187 pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta2 = -pst _ delta2;
192 DO_TICK(4); 188 DO_TICK(4);
193 } 189 }
194 if (cycle == PST tick_cycle1) { 190 if (cycle == pst _ tick_cycle1) {
195 PST tick_cycle1 += PST period_cycles1; 191 pst _ tick_cycle1 += pst _ period_cycles1;
196 if ((PST skctl & 0x88) == 8) 192 if ((pst _ skctl & 0x88) == 8) /* two-tone, sending 1 (i.e. timer1) */
197 PST tick_cycle2 = cycle + PST period_cycles2; 193 pst _ tick_cycle2 = cycle + pst _ period_cycles2;
198 DO_TICK(1); 194 DO_TICK(1);
199 } 195 }
200 if (cycle == PST tick_cycle2) { 196 if (cycle == pst _ tick_cycle2) {
201 PST tick_cycle2 += PST period_cycles2; 197 pst _ tick_cycle2 += pst _ period_cycles2;
202 if ((PST audctl & 0x10) != 0) 198 if ((pst _ audctl & 0x10) != 0)
203 PST tick_cycle1 = cycle + PST reload_cycles1; 199 pst _ tick_cycle1 = cycle + pst _ reload_cycles1;
204 else if ((PST skctl & 8) != 0) 200 else if ((pst _ skctl & 8) != 0) /* two-tone */
205 PST tick_cycle1 = cycle + PST period_cycles1; 201 pst _ tick_cycle1 = cycle + pst _ period_cycles1;
206 DO_TICK(2); 202 DO_TICK(2);
207 } 203 }
208 } 204 }
209} 205}
210 206
207#ifdef APOKEYSND
208
209#define CURRENT_CYCLE 0
210#define CURRENT_SAMPLE 0
211#define DO_STORE(reg) \
212 if (data == pst _ reg) \
213 break; \
214 pst _ reg = data;
215
216#else
217
218#define CURRENT_CYCLE ast _ cycle
219#define CURRENT_SAMPLE CYCLE_TO_SAMPLE(ast _ cycle)
220#define DO_STORE(reg) \
221 if (data == pst _ reg) \
222 break; \
223 PokeySound_GenerateUntilCycle(ast, pst, ast _ cycle); \
224 pst _ reg = data;
225
226#endif /* APOKEYSND */
227
211#define MUTE_CHANNEL(ch, cond, mask) \ 228#define MUTE_CHANNEL(ch, cond, mask) \
212 if (cond) { \ 229 if (cond) { \
213 PST mute##ch |= mask; \ 230 pst _ mute##ch |= mask; \
214 PST tick_cycle##ch = NEVER; \ 231 pst _ tick_cycle##ch = NEVER; \
215 } \ 232 } \
216 else { \ 233 else { \
217 PST mute##ch &= ~mask; \ 234 pst _ mute##ch &= ~mask; \
218 if (PST tick_cycle##ch == NEVER && PST mute##ch == 0) \ 235 if (pst _ tick_cycle##ch == NEVER && pst _ mute##ch == 0) \
219 PST tick_cycle##ch = AST cycle; \ 236 pst _ tick_cycle##ch = CURRENT_CYCLE; \
220 } 237 }
221 238
222#define DO_ULTRASOUND(ch) \ 239#define DO_ULTRASOUND(ch) \
223 MUTE_CHANNEL(ch, PST period_cycles##ch <= ULTRASOUND_CYCLES && (PST audc##ch >> 4 == 10 || PST audc##ch >> 4 == 14), MUTE_FREQUENCY) 240 MUTE_CHANNEL(ch, pst _ period_cycles##ch <= ULTRASOUND_CYCLES && (pst _ audc##ch >> 4 == 10 || pst _ audc##ch >> 4 == 14), MUTE_FREQUENCY)
224 241
225#define DO_AUDC(ch) \ 242#define DO_AUDC(ch) \
226 if (data == PST audc##ch) \ 243 DO_STORE(audc##ch); \
227 break; \
228 generate(ast, pst, AST cycle); \
229 PST audc##ch = data; \
230 if ((data & 0x10) != 0) { \ 244 if ((data & 0x10) != 0) { \
231 data &= 0xf; \ 245 data = (data & 0xf) << DELTA_SHIFT_POKEY; \
232 if ((PST mute##ch & MUTE_USER) == 0) \ 246 if ((pst _ mute##ch & MUTE_USER) == 0) \
233 PST delta_buffer[CYCLE_TO_SAMPLE(AST cycle)] \ 247 pst _ delta_buffer[CURRENT_SAMPLE] \
234 += PST delta##ch > 0 ? data - PST delta##ch : data; \ 248 += pst _ delta##ch > 0 ? data - pst _ delta##ch : data; \
235 PST delta##ch = data; \ 249 pst _ delta##ch = data; \
236 } \ 250 } \
237 else { \ 251 else { \
238 data &= 0xf; \ 252 data = (data & 0xf) << DELTA_SHIFT_POKEY; \
239 DO_ULTRASOUND(ch); \ 253 DO_ULTRASOUND(ch); \
240 if (PST delta##ch > 0) { \ 254 if (pst _ delta##ch > 0) { \
241 if ((PST mute##ch & MUTE_USER) == 0) \ 255 if ((pst _ mute##ch & MUTE_USER) == 0) \
242 PST delta_buffer[CYCLE_TO_SAMPLE(AST cycle)] \ 256 pst _ delta_buffer[CURRENT_SAMPLE] \
243 += data - PST delta##ch; \ 257 += data - pst _ delta##ch; \
244 PST delta##ch = data; \ 258 pst _ delta##ch = data; \
245 } \ 259 } \
246 else \ 260 else \
247 PST delta##ch = -data; \ 261 pst _ delta##ch = -data; \
248 } \ 262 } \
249 break; 263 break;
250 264
251#define DO_INIT(ch, cond) \ 265#define DO_INIT(ch, cond) \
252 MUTE_CHANNEL(ch, PST init && cond, MUTE_INIT) 266 MUTE_CHANNEL(ch, pst _ init && cond, MUTE_INIT)
253 267
254ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data) 268FUNC(void, PokeySound_PutByte, (P(ASAP_State PTR, ast), P(int, addr), P(int, data)))
255{ 269{
256 PokeyState PTR pst = (addr & AST extra_pokey_mask) != 0 270 V(PokeyState PTR, pst) = (addr & ast _ extra_pokey_mask) != 0
257 ? ADDRESSOF AST extra_pokey : ADDRESSOF AST base_pokey; 271 ? ADDRESSOF ast _ extra_pokey : ADDRESSOF ast _ base_pokey;
258 switch (addr & 0xf) { 272 switch (addr & 0xf) {
259 case 0x00: 273 case 0x00:
260 if (data == PST audf1) 274 DO_STORE(audf1);
261 break; 275 switch (pst _ audctl & 0x50) {
262 generate(ast, pst, AST cycle);
263 PST audf1 = data;
264 switch (PST audctl & 0x50) {
265 case 0x00: 276 case 0x00:
266 PST period_cycles1 = PST div_cycles * (data + 1); 277 pst _ period_cycles1 = pst _ div_cycles * (data + 1);
267 break; 278 break;
268 case 0x10: 279 case 0x10:
269 PST period_cycles2 = PST div_cycles * (data + 256 * PST audf2 + 1); 280 pst _ period_cycles2 = pst _ div_cycles * (data + 256 * pst _ audf2 + 1);
270 PST reload_cycles1 = PST div_cycles * (data + 1); 281 pst _ reload_cycles1 = pst _ div_cycles * (data + 1);
271 DO_ULTRASOUND(2); 282 DO_ULTRASOUND(2);
272 break; 283 break;
273 case 0x40: 284 case 0x40:
274 PST period_cycles1 = data + 4; 285 pst _ period_cycles1 = data + 4;
275 break; 286 break;
276 case 0x50: 287 case 0x50:
277 PST period_cycles2 = data + 256 * PST audf2 + 7; 288 pst _ period_cycles2 = data + 256 * pst _ audf2 + 7;
278 PST reload_cycles1 = data + 4; 289 pst _ reload_cycles1 = data + 4;
279 DO_ULTRASOUND(2); 290 DO_ULTRASOUND(2);
280 break; 291 break;
281 } 292 }
@@ -284,20 +295,17 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
284 case 0x01: 295 case 0x01:
285 DO_AUDC(1) 296 DO_AUDC(1)
286 case 0x02: 297 case 0x02:
287 if (data == PST audf2) 298 DO_STORE(audf2);
288 break; 299 switch (pst _ audctl & 0x50) {
289 generate(ast, pst, AST cycle);
290 PST audf2 = data;
291 switch (PST audctl & 0x50) {
292 case 0x00: 300 case 0x00:
293 case 0x40: 301 case 0x40:
294 PST period_cycles2 = PST div_cycles * (data + 1); 302 pst _ period_cycles2 = pst _ div_cycles * (data + 1);
295 break; 303 break;
296 case 0x10: 304 case 0x10:
297 PST period_cycles2 = PST div_cycles * (PST audf1 + 256 * data + 1); 305 pst _ period_cycles2 = pst _ div_cycles * (pst _ audf1 + 256 * data + 1);
298 break; 306 break;
299 case 0x50: 307 case 0x50:
300 PST period_cycles2 = PST audf1 + 256 * data + 7; 308 pst _ period_cycles2 = pst _ audf1 + 256 * data + 7;
301 break; 309 break;
302 } 310 }
303 DO_ULTRASOUND(2); 311 DO_ULTRASOUND(2);
@@ -305,25 +313,22 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
305 case 0x03: 313 case 0x03:
306 DO_AUDC(2) 314 DO_AUDC(2)
307 case 0x04: 315 case 0x04:
308 if (data == PST audf3) 316 DO_STORE(audf3);
309 break; 317 switch (pst _ audctl & 0x28) {
310 generate(ast, pst, AST cycle);
311 PST audf3 = data;
312 switch (PST audctl & 0x28) {
313 case 0x00: 318 case 0x00:
314 PST period_cycles3 = PST div_cycles * (data + 1); 319 pst _ period_cycles3 = pst _ div_cycles * (data + 1);
315 break; 320 break;
316 case 0x08: 321 case 0x08:
317 PST period_cycles4 = PST div_cycles * (data + 256 * PST audf4 + 1); 322 pst _ period_cycles4 = pst _ div_cycles * (data + 256 * pst _ audf4 + 1);
318 PST reload_cycles3 = PST div_cycles * (data + 1); 323 pst _ reload_cycles3 = pst _ div_cycles * (data + 1);
319 DO_ULTRASOUND(4); 324 DO_ULTRASOUND(4);
320 break; 325 break;
321 case 0x20: 326 case 0x20:
322 PST period_cycles3 = data + 4; 327 pst _ period_cycles3 = data + 4;
323 break; 328 break;
324 case 0x28: 329 case 0x28:
325 PST period_cycles4 = data + 256 * PST audf4 + 7; 330 pst _ period_cycles4 = data + 256 * pst _ audf4 + 7;
326 PST reload_cycles3 = data + 4; 331 pst _ reload_cycles3 = data + 4;
327 DO_ULTRASOUND(4); 332 DO_ULTRASOUND(4);
328 break; 333 break;
329 } 334 }
@@ -332,20 +337,17 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
332 case 0x05: 337 case 0x05:
333 DO_AUDC(3) 338 DO_AUDC(3)
334 case 0x06: 339 case 0x06:
335 if (data == PST audf4) 340 DO_STORE(audf4);
336 break; 341 switch (pst _ audctl & 0x28) {
337 generate(ast, pst, AST cycle);
338 PST audf4 = data;
339 switch (PST audctl & 0x28) {
340 case 0x00: 342 case 0x00:
341 case 0x20: 343 case 0x20:
342 PST period_cycles4 = PST div_cycles * (data + 1); 344 pst _ period_cycles4 = pst _ div_cycles * (data + 1);
343 break; 345 break;
344 case 0x08: 346 case 0x08:
345 PST period_cycles4 = PST div_cycles * (PST audf3 + 256 * data + 1); 347 pst _ period_cycles4 = pst _ div_cycles * (pst _ audf3 + 256 * data + 1);
346 break; 348 break;
347 case 0x28: 349 case 0x28:
348 PST period_cycles4 = PST audf3 + 256 * data + 7; 350 pst _ period_cycles4 = pst _ audf3 + 256 * data + 7;
349 break; 351 break;
350 } 352 }
351 DO_ULTRASOUND(4); 353 DO_ULTRASOUND(4);
@@ -353,141 +355,153 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
353 case 0x07: 355 case 0x07:
354 DO_AUDC(4) 356 DO_AUDC(4)
355 case 0x08: 357 case 0x08:
356 if (data == PST audctl) 358 DO_STORE(audctl);
357 break; 359 pst _ div_cycles = ((data & 1) != 0) ? 114 : 28;
358 generate(ast, pst, AST cycle);
359 PST audctl = data;
360 PST div_cycles = ((data & 1) != 0) ? 114 : 28;
361 /* TODO: tick_cycles */ 360 /* TODO: tick_cycles */
362 switch (data & 0x50) { 361 switch (data & 0x50) {
363 case 0x00: 362 case 0x00:
364 PST period_cycles1 = PST div_cycles * (PST audf1 + 1); 363 pst _ period_cycles1 = pst _ div_cycles * (pst _ audf1 + 1);
365 PST period_cycles2 = PST div_cycles * (PST audf2 + 1); 364 pst _ period_cycles2 = pst _ div_cycles * (pst _ audf2 + 1);
366 break; 365 break;
367 case 0x10: 366 case 0x10:
368 PST period_cycles1 = PST div_cycles * 256; 367 pst _ period_cycles1 = pst _ div_cycles * 256;
369 PST period_cycles2 = PST div_cycles * (PST audf1 + 256 * PST audf2 + 1); 368 pst _ period_cycles2 = pst _ div_cycles * (pst _ audf1 + 256 * pst _ audf2 + 1);
370 PST reload_cycles1 = PST div_cycles * (PST audf1 + 1); 369 pst _ reload_cycles1 = pst _ div_cycles * (pst _ audf1 + 1);
371 break; 370 break;
372 case 0x40: 371 case 0x40:
373 PST period_cycles1 = PST audf1 + 4; 372 pst _ period_cycles1 = pst _ audf1 + 4;
374 PST period_cycles2 = PST div_cycles * (PST audf2 + 1); 373 pst _ period_cycles2 = pst _ div_cycles * (pst _ audf2 + 1);
375 break; 374 break;
376 case 0x50: 375 case 0x50:
377 PST period_cycles1 = 256; 376 pst _ period_cycles1 = 256;
378 PST period_cycles2 = PST audf1 + 256 * PST audf2 + 7; 377 pst _ period_cycles2 = pst _ audf1 + 256 * pst _ audf2 + 7;
379 PST reload_cycles1 = PST audf1 + 4; 378 pst _ reload_cycles1 = pst _ audf1 + 4;
380 break; 379 break;
381 } 380 }
382 DO_ULTRASOUND(1); 381 DO_ULTRASOUND(1);
383 DO_ULTRASOUND(2); 382 DO_ULTRASOUND(2);
384 switch (data & 0x28) { 383 switch (data & 0x28) {
385 case 0x00: 384 case 0x00:
386 PST period_cycles3 = PST div_cycles * (PST audf3 + 1); 385 pst _ period_cycles3 = pst _ div_cycles * (pst _ audf3 + 1);
387 PST period_cycles4 = PST div_cycles * (PST audf4 + 1); 386 pst _ period_cycles4 = pst _ div_cycles * (pst _ audf4 + 1);
388 break; 387 break;
389 case 0x08: 388 case 0x08:
390 PST period_cycles3 = PST div_cycles * 256; 389 pst _ period_cycles3 = pst _ div_cycles * 256;
391 PST period_cycles4 = PST div_cycles * (PST audf3 + 256 * PST audf4 + 1); 390 pst _ period_cycles4 = pst _ div_cycles * (pst _ audf3 + 256 * pst _ audf4 + 1);
392 PST reload_cycles3 = PST div_cycles * (PST audf3 + 1); 391 pst _ reload_cycles3 = pst _ div_cycles * (pst _ audf3 + 1);
393 break; 392 break;
394 case 0x20: 393 case 0x20:
395 PST period_cycles3 = PST audf3 + 4; 394 pst _ period_cycles3 = pst _ audf3 + 4;
396 PST period_cycles4 = PST div_cycles * (PST audf4 + 1); 395 pst _ period_cycles4 = pst _ div_cycles * (pst _ audf4 + 1);
397 break; 396 break;
398 case 0x28: 397 case 0x28:
399 PST period_cycles3 = 256; 398 pst _ period_cycles3 = 256;
400 PST period_cycles4 = PST audf3 + 256 * PST audf4 + 7; 399 pst _ period_cycles4 = pst _ audf3 + 256 * pst _ audf4 + 7;
401 PST reload_cycles3 = PST audf3 + 4; 400 pst _ reload_cycles3 = pst _ audf3 + 4;
402 break; 401 break;
403 } 402 }
404 DO_ULTRASOUND(3); 403 DO_ULTRASOUND(3);
405 DO_ULTRASOUND(4); 404 DO_ULTRASOUND(4);
405 DO_INIT(1, (data & 0x40) == 0);
406 DO_INIT(2, (data & 0x50) != 0x50);
407 DO_INIT(3, (data & 0x20) == 0);
408 DO_INIT(4, (data & 0x28) != 0x28);
406 break; 409 break;
407 case 0x09: 410 case 0x09:
408 /* TODO: STIMER */ 411 /* TODO: STIMER */
409 break; 412 break;
410 case 0x0f: 413 case 0x0f:
411 PST skctl = data; 414 DO_STORE(skctl);
412 PST init = ((data & 3) == 0); 415 pst _ init = ((data & 3) == 0);
413 DO_INIT(1, (PST audctl & 0x40) == 0); 416 DO_INIT(1, (pst _ audctl & 0x40) == 0);
414 DO_INIT(2, (PST audctl & 0x50) != 0x50); 417 DO_INIT(2, (pst _ audctl & 0x50) != 0x50);
415 DO_INIT(3, (PST audctl & 0x20) == 0); 418 DO_INIT(3, (pst _ audctl & 0x20) == 0);
416 DO_INIT(4, (PST audctl & 0x28) != 0x28); 419 DO_INIT(4, (pst _ audctl & 0x28) != 0x28);
417 break; 420 break;
418 default: 421 default:
419 break; 422 break;
420 } 423 }
421} 424}
422 425
423ASAP_FUNC int PokeySound_GetRandom(ASAP_State PTR ast, int addr) 426FUNC(int, PokeySound_GetRandom, (P(ASAP_State PTR, ast), P(int, addr), P(int, cycle)))
424{ 427{
425 PokeyState PTR pst = (addr & AST extra_pokey_mask) != 0 428 V(PokeyState PTR, pst) = (addr & ast _ extra_pokey_mask) != 0
426 ? ADDRESSOF AST extra_pokey : ADDRESSOF AST base_pokey; 429 ? ADDRESSOF ast _ extra_pokey : ADDRESSOF ast _ base_pokey;
427 int i; 430 V(int, i);
428 if (PST init) 431 if (pst _ init)
429 return 0xff; 432 return 0xff;
430 i = AST cycle + PST poly_index; 433 i = cycle + pst _ poly_index;
431 if ((PST audctl & 0x80) != 0) 434 if ((pst _ audctl & 0x80) != 0)
432 return AST poly9_lookup[i % 511]; 435 return ast _ poly9_lookup[i % 511];
433 else { 436 else {
434 int j; 437 V(int, j);
435 i %= 131071; 438 i %= 131071;
436 j = i >> 3; 439 j = i >> 3;
437 i &= 7; 440 i &= 7;
438 return ((AST poly17_lookup[j] >> i) + (AST poly17_lookup[j + 1] << (8 - i))) & 0xff; 441 return ((ast _ poly17_lookup[j] >> i) + (ast _ poly17_lookup[j + 1] << (8 - i))) & 0xff;
439 } 442 }
440} 443}
441 444
442FILE_FUNC void end_frame(ASAP_State PTR ast, PokeyState PTR pst, int cycle_limit) 445PRIVATE FUNC(void, end_frame, (P(ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, cycle_limit)))
443{ 446{
444 int m; 447 V(int, m);
445 generate(ast, pst, cycle_limit); 448 PokeySound_GenerateUntilCycle(ast, pst, cycle_limit);
446 PST poly_index += cycle_limit; 449 pst _ poly_index += cycle_limit;
447 m = ((PST audctl & 0x80) != 0) ? 15 * 31 * 511 : 15 * 31 * 131071; 450 m = ((pst _ audctl & 0x80) != 0) ? 15 * 31 * 511 : 15 * 31 * 131071;
448 if (PST poly_index >= 2 * m) 451 if (pst _ poly_index >= 2 * m)
449 PST poly_index -= m; 452 pst _ poly_index -= m;
450 if (PST tick_cycle1 != NEVER) 453 if (pst _ tick_cycle1 != NEVER)
451 PST tick_cycle1 -= cycle_limit; 454 pst _ tick_cycle1 -= cycle_limit;
452 if (PST tick_cycle2 != NEVER) 455 if (pst _ tick_cycle2 != NEVER)
453 PST tick_cycle2 -= cycle_limit; 456 pst _ tick_cycle2 -= cycle_limit;
454 if (PST tick_cycle3 != NEVER) 457 if (pst _ tick_cycle3 != NEVER)
455 PST tick_cycle3 -= cycle_limit; 458 pst _ tick_cycle3 -= cycle_limit;
456 if (PST tick_cycle4 != NEVER) 459 if (pst _ tick_cycle4 != NEVER)
457 PST tick_cycle4 -= cycle_limit; 460 pst _ tick_cycle4 -= cycle_limit;
458} 461}
459 462
460ASAP_FUNC void PokeySound_StartFrame(ASAP_State PTR ast) 463FUNC(void, PokeySound_StartFrame, (P(ASAP_State PTR, ast)))
461{ 464{
462 ZERO_ARRAY(AST base_pokey.delta_buffer); 465 ZERO_ARRAY(ast _ base_pokey.delta_buffer);
463 if (AST extra_pokey_mask != 0) 466 if (ast _ extra_pokey_mask != 0)
464 ZERO_ARRAY(AST extra_pokey.delta_buffer); 467 ZERO_ARRAY(ast _ extra_pokey.delta_buffer);
465} 468}
466 469
467ASAP_FUNC void PokeySound_EndFrame(ASAP_State PTR ast, int current_cycle) 470FUNC(void, PokeySound_EndFrame, (P(ASAP_State PTR, ast), P(int, current_cycle)))
468{ 471{
469 end_frame(ast, ADDRESSOF AST base_pokey, current_cycle); 472 end_frame(ast, ADDRESSOF ast _ base_pokey, current_cycle);
470 if (AST extra_pokey_mask != 0) 473 if (ast _ extra_pokey_mask != 0)
471 end_frame(ast, ADDRESSOF AST extra_pokey, current_cycle); 474 end_frame(ast, ADDRESSOF ast _ extra_pokey, current_cycle);
472 AST sample_offset += current_cycle * ASAP_SAMPLE_RATE; 475 ast _ sample_offset += current_cycle * ASAP_SAMPLE_RATE;
473 AST sample_index = 0; 476 ast _ sample_index = 0;
474 AST samples = AST sample_offset / ASAP_MAIN_CLOCK; 477 ast _ samples = TO_INT(ast _ sample_offset / ASAP_MAIN_CLOCK);
475 AST sample_offset %= ASAP_MAIN_CLOCK; 478 ast _ sample_offset %= ASAP_MAIN_CLOCK;
476} 479}
477 480
478ASAP_FUNC int PokeySound_Generate(ASAP_State PTR ast, byte ARRAY buffer, int buffer_offset, int blocks, ASAP_SampleFormat format) 481/* Fills buffer with samples from delta_buffer. */
482FUNC(int, PokeySound_Generate, (P(ASAP_State PTR, ast), P(BYTEARRAY, buffer), P(int, buffer_offset), P(int, blocks), P(ASAP_SampleFormat, format)))
479{ 483{
480 int i = AST sample_index; 484 V(int, i) = ast _ sample_index;
481 int samples = AST samples; 485 V(int, samples) = ast _ samples;
482 int acc_left = AST iir_acc_left; 486 V(int, acc_left) = ast _ iir_acc_left;
483 int acc_right = AST iir_acc_right; 487 V(int, acc_right) = ast _ iir_acc_right;
484 if (blocks < samples - i) 488 if (blocks < samples - i)
485 samples = i + blocks; 489 samples = i + blocks;
486 else 490 else
487 blocks = samples - i; 491 blocks = samples - i;
488 for (; i < samples; i++) { 492 for (; i < samples; i++) {
489 int sample; 493#ifdef ACTIONSCRIPT
490 acc_left += (AST base_pokey.delta_buffer[i] << 20) - (acc_left * 3 >> 10); 494 acc_left += ast _ base_pokey.delta_buffer[i] - (acc_left * 3 >> 10);
495 var sample : Number = acc_left / 33553408;
496 buffer.writeFloat(sample);
497 if (ast.extra_pokey_mask != 0) {
498 acc_right += ast _ extra_pokey.delta_buffer[i] - (acc_right * 3 >> 10);
499 sample = acc_right / 33553408;
500 }
501 buffer.writeFloat(sample);
502#else
503 V(int, sample);
504 acc_left += ast _ base_pokey.delta_buffer[i] - (acc_left * 3 >> 10);
491 sample = acc_left >> 10; 505 sample = acc_left >> 10;
492#define STORE_SAMPLE \ 506#define STORE_SAMPLE \
493 if (sample < -32767) \ 507 if (sample < -32767) \
@@ -496,43 +510,89 @@ ASAP_FUNC int PokeySound_Generate(ASAP_State PTR ast, byte ARRAY buffer, int buf
496 sample = 32767; \ 510 sample = 32767; \
497 switch (format) { \ 511 switch (format) { \
498 case ASAP_FORMAT_U8: \ 512 case ASAP_FORMAT_U8: \
499 buffer[buffer_offset++] = (byte) ((sample >> 8) + 128); \ 513 buffer[buffer_offset++] = CAST(byte) ((sample >> 8) + 128); \
500 break; \ 514 break; \
501 case ASAP_FORMAT_S16_LE: \ 515 case ASAP_FORMAT_S16_LE: \
502 buffer[buffer_offset++] = (byte) sample; \ 516 buffer[buffer_offset++] = TO_BYTE(sample); \
503 buffer[buffer_offset++] = (byte) (sample >> 8); \ 517 buffer[buffer_offset++] = TO_BYTE(sample >> 8); \
504 break; \ 518 break; \
505 case ASAP_FORMAT_S16_BE: \ 519 case ASAP_FORMAT_S16_BE: \
506 buffer[buffer_offset++] = (byte) (sample >> 8); \ 520 buffer[buffer_offset++] = TO_BYTE(sample >> 8); \
507 buffer[buffer_offset++] = (byte) sample; \ 521 buffer[buffer_offset++] = TO_BYTE(sample); \
508 break; \ 522 break; \
509 } 523 }
510 STORE_SAMPLE; 524 STORE_SAMPLE;
511 if (AST extra_pokey_mask != 0) { 525 if (ast _ extra_pokey_mask != 0) {
512 acc_right += (AST extra_pokey.delta_buffer[i] << 20) - (acc_right * 3 >> 10); 526 acc_right += ast _ extra_pokey.delta_buffer[i] - (acc_right * 3 >> 10);
513 sample = acc_right >> 10; 527 sample = acc_right >> 10;
514 STORE_SAMPLE; 528 STORE_SAMPLE;
515 } 529 }
530#endif /* ACTIONSCRIPT */
516 } 531 }
517 if (i == AST samples) { 532 if (i == ast _ samples) {
518 acc_left += AST base_pokey.delta_buffer[i] << 20; 533 acc_left += ast _ base_pokey.delta_buffer[i];
519 acc_right += AST extra_pokey.delta_buffer[i] << 20; 534 acc_right += ast _ extra_pokey.delta_buffer[i];
520 } 535 }
521 AST sample_index = i; 536 ast _ sample_index = i;
522 AST iir_acc_left = acc_left; 537 ast _ iir_acc_left = acc_left;
523 AST iir_acc_right = acc_right; 538 ast _ iir_acc_right = acc_right;
539#ifdef APOKEYSND
540 return buffer_offset;
541#else
524 return blocks; 542 return blocks;
543#endif
525} 544}
526 545
527ASAP_FUNC abool PokeySound_IsSilent(const PokeyState PTR pst) 546FUNC(abool, PokeySound_IsSilent, (P(CONST PokeyState PTR, pst)))
528{ 547{
529 return ((PST audc1 | PST audc2 | PST audc3 | PST audc4) & 0xf) == 0; 548 return ((pst _ audc1 | pst _ audc2 | pst _ audc3 | pst _ audc4) & 0xf) == 0;
530} 549}
531 550
532ASAP_FUNC void PokeySound_Mute(const ASAP_State PTR ast, PokeyState PTR pst, int mask) 551FUNC(void, PokeySound_Mute, (P(CONST ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, mask)))
533{ 552{
534 MUTE_CHANNEL(1, (mask & 1) != 0, MUTE_USER); 553 MUTE_CHANNEL(1, (mask & 1) != 0, MUTE_USER);
535 MUTE_CHANNEL(2, (mask & 2) != 0, MUTE_USER); 554 MUTE_CHANNEL(2, (mask & 2) != 0, MUTE_USER);
536 MUTE_CHANNEL(3, (mask & 4) != 0, MUTE_USER); 555 MUTE_CHANNEL(3, (mask & 4) != 0, MUTE_USER);
537 MUTE_CHANNEL(4, (mask & 8) != 0, MUTE_USER); 556 MUTE_CHANNEL(4, (mask & 8) != 0, MUTE_USER);
538} 557}
558
559#ifdef APOKEYSND
560
561static ASAP_State asap;
562
563__declspec(dllexport) void APokeySound_Initialize(abool stereo)
564{
565 asap.extra_pokey_mask = stereo ? 0x10 : 0;
566 PokeySound_Initialize(&asap);
567 PokeySound_Mute(&asap, &asap.base_pokey, 0);
568 PokeySound_Mute(&asap, &asap.extra_pokey, 0);
569 PokeySound_StartFrame(&asap);
570}
571
572__declspec(dllexport) void APokeySound_PutByte(int addr, int data)
573{
574 PokeySound_PutByte(&asap, addr, data);
575}
576
577__declspec(dllexport) int APokeySound_GetRandom(int addr, int cycle)
578{
579 return PokeySound_GetRandom(&asap, addr, cycle);
580}
581
582__declspec(dllexport) int APokeySound_Generate(int cycles, byte buffer[], ASAP_SampleFormat format)
583{
584 int len;
585 PokeySound_EndFrame(&asap, cycles);
586 len = PokeySound_Generate(&asap, buffer, 0, asap.samples, format);
587 PokeySound_StartFrame(&asap);
588 return len;
589}
590
591__declspec(dllexport) void APokeySound_About(const char **name, const char **author, const char **description)
592{
593 *name = "Another POKEY sound emulator, v" ASAP_VERSION;
594 *author = "Piotr Fusik, (C) " ASAP_YEARS;
595 *description = "Part of ASAP, http://asap.sourceforge.net";
596}
597
598#endif /* APOKEYSND */