This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_mintaudio_mcsn.c
401 lines (334 loc) · 11.6 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2004 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
22
#include "SDL_config.h"
23
24
25
26
27
28
29
30
/*
MiNT audio driver
using XBIOS functions (MacSound compatible driver)
Patrice Mandin
*/
31
#include <support.h>
32
33
34
35
36
37
38
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_audio.h"
39
40
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
41
42
#include "../../video/ataricommon/SDL_atarimxalloc_c.h"
43
44
45
46
47
48
49
50
51
52
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_mcsn.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_mcsn"
/* Debug print info */
#define DEBUG_NAME "audio:mcsn: "
53
#if 0
54
55
56
57
58
59
60
61
62
63
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
64
65
66
static unsigned long cookie_snd = 0;
static unsigned long cookie_mch = 0;
static cookie_mcsn_t *cookie_mcsn = NULL;
67
68
static int
69
MINTMCSN_Available(void)
70
{
71
unsigned long dummy = 0;
72
73
SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
74
75
76
77
78
/* We can't use XBIOS in interrupt with Magic, don't know about thread */
if (Getcookie(C_MagX, &dummy) == C_FOUND) {
return (0);
}
79
80
81
82
83
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST;
}
84
85
86
87
88
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
89
90
91
92
93
94
/* Check if we have 16 bits audio */
if ((cookie_snd & SND_16BIT) == 0) {
DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
return (0);
}
95
96
97
98
99
100
/* Cookie MCSN present ? */
if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
return (0);
}
101
102
103
104
105
106
/* Check if interrupt at end of replay */
if (cookie_mcsn->pint == 0) {
DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
return (0);
}
107
108
109
110
111
112
/* Check if audio is lockable */
if (Locksnd() != 1) {
DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
return (0);
}
113
114
Unlocksnd();
115
116
117
DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
return (1);
118
119
}
120
static void
121
MINTMCSN_LockDevice(_THIS)
122
{
123
124
/* Stop replay */
Buffoper(0);
125
126
}
127
static void
128
MINTMCSN_UnlockDevice(_THIS)
129
{
130
131
/* Restart replay */
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
132
133
}
134
static void
135
MINTMCSN_CloseDevice(_THIS)
136
{
137
138
139
140
141
142
143
144
145
if (this->hidden != NULL) {
/* Stop replay */
SDL_MintAudio_WaitThread();
Buffoper(0);
if (!SDL_MintAudio_mint_present) {
/* Uninstall interrupt */
Jdisint(MFP_DMASOUND);
}
146
147
148
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {}
149
150
151
152
153
154
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
155
156
157
/* Unlock sound system */
Unlocksnd();
158
159
160
161
SDL_free(this->hidden);
this->hidden = NULL;
}
162
163
}
164
static int
165
MINTMCSN_CheckAudio(_THIS)
166
{
167
168
169
int i;
unsigned long masterclock, masterprediv;
170
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
171
172
173
174
175
176
177
178
179
SDL_AUDIO_BITSIZE(this->spec.format)));
DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
DEBUG_PRINT(("channels=%d, ", this->spec.channels));
DEBUG_PRINT(("freq=%d\n", this->spec.freq));
if (this->spec.channels > 2) {
this->spec.channels = 2; /* no more than stereo! */
180
181
}
182
183
184
185
/* Check formats available */
MINTAUDIO_freqcount = 0;
switch (cookie_mcsn->play) {
case MCSN_ST:
186
187
this->spec.channels = 1;
this->spec.format = AUDIO_S8; /* FIXME: is it signed or unsigned ? */
188
189
190
SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1);
break;
case MCSN_TT: /* Also STE, Mega STE */
191
this->spec.format = AUDIO_S8;
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
masterclock = MASTERCLOCK_STE;
masterprediv = MASTERPREDIV_STE;
if ((cookie_mch >> 16) == MCH_TT) {
masterclock = MASTERCLOCK_TT;
masterprediv = MASTERPREDIV_TT;
}
for (i = 0; i < 4; i++) {
SDL_MintAudio_AddFrequency(this,
masterclock / (masterprediv *
(1 << i)),
masterclock, 3 - i, -1);
}
break;
case MCSN_FALCON: /* Also Mac */
for (i = 1; i < 12; i++) {
/* Remove unusable Falcon codec predivisors */
if ((i == 6) || (i == 8) || (i == 10)) {
continue;
}
SDL_MintAudio_AddFrequency(this,
MASTERCLOCK_FALCON1 /
(MASTERPREDIV_FALCON * (i + 1)),
CLK25M, i + 1, -1);
}
if (cookie_mcsn->res1 != 0) {
for (i = 1; i < 4; i++) {
SDL_MintAudio_AddFrequency(this,
(cookie_mcsn->res1) /
(MASTERPREDIV_FALCON *
(1 << i)), CLKEXT,
(1 << i) - 1, -1);
}
}
225
226
227
228
this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */
if ((SDL_AUDIO_BITSIZE(this->spec.format)) == 16) {
this->spec.format |= SDL_AUDIO_MASK_ENDIAN; /* Audio is always big endian */
this->spec.channels = 2; /* 16 bits always stereo */
229
230
231
}
break;
}
232
233
#if 1
234
235
236
237
238
239
for (i = 0; i < MINTAUDIO_freqcount; i++) {
DEBUG_PRINT((DEBUG_NAME "freq %d: %lu Hz, clock %lu, prediv %d\n",
i, MINTAUDIO_frequencies[i].frequency,
MINTAUDIO_frequencies[i].masterclock,
MINTAUDIO_frequencies[i].predivisor));
}
240
241
#endif
242
243
MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
244
245
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
246
247
248
249
250
251
SDL_AUDIO_BITSIZE(this->spec.format)));
DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
DEBUG_PRINT(("channels=%d, ", this->spec.channels));
DEBUG_PRINT(("freq=%d\n", this->spec.freq));
252
253
return 0;
254
255
}
256
static void
257
MINTMCSN_InitAudio(_THIS)
258
{
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
int channels_mode, prediv, dmaclock;
void *buffer;
/* Stop currently playing sound */
SDL_MintAudio_quit_thread = SDL_FALSE;
SDL_MintAudio_thread_finished = SDL_TRUE;
SDL_MintAudio_WaitThread();
Buffoper(0);
/* Set replay tracks */
Settracks(0, 0);
Setmontracks(0);
/* Select replay format */
channels_mode = STEREO16;
274
switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
275
case 8:
276
if (this->spec.channels == 2) {
277
278
279
280
281
282
283
284
285
channels_mode = STEREO8;
} else {
channels_mode = MONO8;
}
break;
}
if (Setmode(channels_mode) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
}
286
287
288
289
290
291
292
293
294
295
296
297
298
299
dmaclock = MINTAUDIO_frequencies[MINTAUDIO_numfreq].masterclock;
prediv = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
switch (cookie_mcsn->play) {
case MCSN_TT:
Devconnect(DMAPLAY, DAC, CLK25M, CLKOLD, 1);
Soundcmd(SETPRESCALE, prediv);
DEBUG_PRINT((DEBUG_NAME "STE/TT prescaler selected\n"));
break;
case MCSN_FALCON:
Devconnect(DMAPLAY, DAC, dmaclock, prediv, 1);
DEBUG_PRINT((DEBUG_NAME "Falcon prescaler selected\n"));
break;
}
300
301
302
/* Set buffer */
buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
303
if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
304
305
DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
}
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
if (SDL_MintAudio_mint_present) {
SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
} else {
/* Install interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
Jenabint(MFP_DMASOUND);
if (Setinterrupt(SI_TIMERA, SI_PLAY) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
}
/* Go */
Buffoper(SB_PLA_ENA | SB_PLA_RPT);
DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
323
324
}
325
static int
326
MINTMCSN_OpenDevice(_THIS, const char *devname, int iscapture)
327
{
328
329
/* Lock sound system */
if (Locksnd() != 1) {
330
331
SDL_SetError("MINTMCSN_OpenDevice: Audio system already in use");
return 0;
332
}
333
334
SDL_MintAudio_device = this;
335
336
/* Check audio capabilities */
337
338
if (MINTMCSN_CheckAudio(this) == -1) {
return 0;
339
}
340
341
342
343
344
345
346
347
348
349
350
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
SDL_CalculateAudioSpec(&this->spec);
351
352
/* Allocate memory for audio buffers in DMA-able RAM */
353
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
354
355
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
356
if (SDL_MintAudio_audiobuf[0] == NULL) {
357
358
359
360
SDL_free(this->hidden);
this->hidden = NULL;
SDL_OutOfMemory();
return 0;
361
}
362
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
363
SDL_MintAudio_numbuf = 0;
364
365
SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
SDL_MintAudio_audiosize = this->spec.size;
366
SDL_MintAudio_mutex = 0;
367
368
369
370
371
DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
SDL_MintAudio_audiobuf[0]));
DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n",
SDL_MintAudio_audiobuf[1]));
372
373
374
SDL_MintAudio_CheckFpu();
375
/* Setup audio hardware */
376
MINTMCSN_InitAudio(this);
377
378
return 1; /* good to go. */
379
}
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
static int
MINTMCSN_Init(SDL_AudioDriverImpl *impl)
{
/* Set the function pointers */
impl->OpenDevice = MINTMCSN_OpenDevice;
impl->CloseDevice = MINTMCSN_CloseDevice;
impl->LockAudio = MINTMCSN_LockAudio;
impl->UnlockAudio = MINTMCSN_UnlockAudio;
impl->OnlyHasDefaultOutputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
impl->SkipMixerLock = 1;
return 1;
}
AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
MINTMCSN_Available, MINTMCSN_Init, 0
};
401
/* vi: set ts=4 sw=4 expandtab: */