This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_mintaudio_dma8.c
348 lines (279 loc) · 9.31 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2009 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
31
32
33
34
35
36
/*
MiNT audio driver
using DMA 8bits (hardware access)
Patrice Mandin
*/
/* Mint includes */
#include <mint/osbind.h>
#include <mint/falcon.h>
#include <mint/cookie.h>
#include "SDL_audio.h"
37
38
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
39
40
#include "../../video/ataricommon/SDL_atarimxalloc_c.h"
41
42
43
44
45
46
47
48
49
50
#include "SDL_mintaudio.h"
#include "SDL_mintaudio_dma8.h"
/*--- Defines ---*/
#define MINT_AUDIO_DRIVER_NAME "mint_dma8"
/* Debug print info */
#define DEBUG_NAME "audio:dma8: "
51
#if 0
52
53
54
55
56
57
58
59
60
61
62
63
#define DEBUG_PRINT(what) \
{ \
printf what; \
}
#else
#define DEBUG_PRINT(what)
#endif
/*--- Static variables ---*/
static unsigned long cookie_snd, cookie_mch;
64
static void
65
MINTDMA8_LockDevice(_THIS)
66
{
67
void *oldpile;
68
69
70
71
72
/* Stop replay */
oldpile = (void *) Super(0);
DMAAUDIO_IO.control = 0;
Super(oldpile);
73
74
}
75
static void
76
MINTDMA8_UnlockDevice(_THIS)
77
{
78
void *oldpile;
79
80
81
82
83
/* Restart replay */
oldpile = (void *) Super(0);
DMAAUDIO_IO.control = 3;
Super(oldpile);
84
85
}
86
static void
87
MINTDMA8_CloseDevice(_THIS)
88
{
89
90
91
if (this->hidden != NULL) {
/* Stop replay */
void *oldpile = (void *) Super(0);
92
93
94
DMAAUDIO_IO.control = 0;
Super(oldpile);
95
96
DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
97
98
99
/* Disable interrupt */
Jdisint(MFP_DMASOUND);
100
101
DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
102
103
/* Wait if currently playing sound */
104
105
while (SDL_MintAudio_mutex != 0) {
}
106
107
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
108
109
110
111
112
113
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
114
115
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
116
117
SDL_free(this->hidden);
this->hidden = NULL;
118
}
119
120
}
121
static int
122
MINTDMA8_CheckAudio(_THIS)
123
{
124
125
126
int i, masterprediv, sfreq;
unsigned long masterclock;
127
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
128
129
130
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)));
131
132
DEBUG_PRINT(("big endian=%d, ",
SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
133
134
135
136
DEBUG_PRINT(("channels=%d, ", this->spec.channels));
DEBUG_PRINT(("freq=%d\n", this->spec.freq));
if (this->spec.channels > 2) {
137
this->spec.channels = 2; /* no more than stereo! */
138
139
}
140
/* Check formats available */
141
this->spec.format = AUDIO_S8;
142
143
144
145
146
147
/* Calculate and select the closest frequency */
sfreq = 0;
masterclock = MASTERCLOCK_STE;
masterprediv = MASTERPREDIV_STE;
switch (cookie_mch >> 16) {
148
149
150
151
152
153
/*
case MCH_STE:
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
break;
*/
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
case MCH_TT:
masterclock = MASTERCLOCK_TT;
masterprediv = MASTERPREDIV_TT;
break;
case MCH_F30:
case MCH_ARANYM:
masterclock = MASTERCLOCK_FALCON1;
masterprediv = MASTERPREDIV_FALCON;
sfreq = 1;
break;
}
MINTAUDIO_freqcount = 0;
for (i = sfreq; i < 4; i++) {
SDL_MintAudio_AddFrequency(this,
masterclock / (masterprediv * (1 << i)),
masterclock, i - sfreq, -1);
}
172
173
#if 1
174
175
176
177
178
179
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));
}
180
181
#endif
182
183
MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
184
185
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
186
187
188
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)));
189
190
DEBUG_PRINT(("big endian=%d, ",
SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
191
192
DEBUG_PRINT(("channels=%d, ", this->spec.channels));
DEBUG_PRINT(("freq=%d\n", this->spec.freq));
193
194
return 0;
195
196
}
197
static void
198
MINTDMA8_InitAudio(_THIS)
199
{
200
201
202
203
204
205
206
207
208
void *oldpile;
unsigned long buffer;
unsigned char mode;
/* Set replay tracks */
if (cookie_snd & SND_16BIT) {
Settracks(0, 0);
Setmontracks(0);
}
209
210
oldpile = (void *) Super(0);
211
212
213
/* Stop currently playing sound */
DMAAUDIO_IO.control = 0;
214
215
216
217
218
219
/* Set buffer */
buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
DMAAUDIO_IO.start_high = (buffer >> 16) & 255;
DMAAUDIO_IO.start_mid = (buffer >> 8) & 255;
DMAAUDIO_IO.start_low = buffer & 255;
220
221
222
223
224
buffer += SDL_MintAudio_audiosize;
DMAAUDIO_IO.end_high = (buffer >> 16) & 255;
DMAAUDIO_IO.end_mid = (buffer >> 8) & 255;
DMAAUDIO_IO.end_low = buffer & 255;
225
226
mode = 3 - MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
227
if (this->spec.channels == 1) {
228
229
230
mode |= 1 << 7;
}
DMAAUDIO_IO.sound_ctrl = mode;
231
232
233
234
235
/* Set interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
Jenabint(MFP_DMASOUND);
236
237
238
239
240
241
if (cookie_snd & SND_16BIT) {
if (Setinterrupt(SI_TIMERA, SI_PLAY) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
}
242
243
244
/* Go */
DMAAUDIO_IO.control = 3; /* playback + repeat */
245
246
Super(oldpile);
247
248
}
249
static int
250
MINTDMA8_OpenDevice(_THIS, const char *devname, int iscapture)
251
{
252
SDL_MintAudio_device = this;
253
254
/* Check audio capabilities */
255
256
if (MINTDMA8_CheckAudio(this) == -1) {
return 0;
257
}
258
259
260
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
261
SDL_malloc((sizeof *this->hidden));
262
263
264
265
266
267
268
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
SDL_CalculateAudioSpec(&this->spec);
269
270
/* Allocate memory for audio buffers in DMA-able RAM */
271
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
272
273
274
SDL_MintAudio_audiobuf[0] =
Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
275
if (SDL_MintAudio_audiobuf[0] == NULL) {
276
277
278
279
SDL_free(this->hidden);
this->hidden = NULL;
SDL_OutOfMemory();
return 0;
280
}
281
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
282
SDL_MintAudio_numbuf = 0;
283
284
SDL_memset(SDL_MintAudio_audiobuf[0], this->spec.silence,
this->spec.size * 2);
285
SDL_MintAudio_audiosize = this->spec.size;
286
SDL_MintAudio_mutex = 0;
287
288
289
290
291
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]));
292
293
294
SDL_MintAudio_CheckFpu();
295
/* Setup audio hardware */
296
MINTDMA8_InitAudio(this);
297
298
return 1; /* good to go. */
299
}
300
301
static int
302
MINTDMA8_Init(SDL_AudioDriverImpl * impl)
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
{
/* Cookie _MCH present ? if not, assume ST machine */
if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
cookie_mch = MCH_ST;
}
/* Cookie _SND present ? if not, assume ST machine */
if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
cookie_snd = SND_PSG;
}
/* Check if we have 8 bits audio */
if ((cookie_snd & SND_8BIT) == 0) {
SDL_SetError(DEBUG_NAME "no 8 bits sound");
return 0;
}
/* Check if audio is lockable */
if (cookie_snd & SND_16BIT) {
if (Locksnd() != 1) {
SDL_SetError(DEBUG_NAME "audio locked by other application");
return 0;
}
Unlocksnd();
}
DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
/* Set the function pointers */
impl->OpenDevice = MINTDMA8_OpenDevice;
impl->CloseDevice = MINTDMA8_CloseDevice;
335
336
impl->LockDevice = MINTDMA8_LockDevice;
impl->UnlockDevice = MINTDMA8_UnlockDevice;
337
338
339
340
impl->OnlyHasDefaultOutputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
impl->SkipMixerLock = 1;
341
return 2; /* 2 == definitely has an audio device. */
342
343
344
345
346
347
}
AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", MINTDMA8_Init, 0
};
348
/* vi: set ts=4 sw=4 expandtab: */