This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_mintaudio_dma8.c
343 lines (274 loc) · 9.18 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
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
104
/* Wait if currently playing sound */
while (SDL_MintAudio_mutex != 0) {}
105
106
DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
107
108
109
110
111
112
/* Clear buffers */
if (SDL_MintAudio_audiobuf[0]) {
Mfree(SDL_MintAudio_audiobuf[0]);
SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
}
113
114
115
116
117
DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
SDL_free(this->buffer);
this->buffer = NULL;
}
118
119
}
120
static int
121
MINTDMA8_CheckAudio(_THIS)
122
{
123
124
125
int i, masterprediv, sfreq;
unsigned long masterclock;
126
DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
127
128
129
130
131
132
133
134
135
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! */
136
137
}
138
/* Check formats available */
139
this->spec.format = AUDIO_S8;
140
141
142
143
144
145
/* Calculate and select the closest frequency */
sfreq = 0;
masterclock = MASTERCLOCK_STE;
masterprediv = MASTERPREDIV_STE;
switch (cookie_mch >> 16) {
146
147
148
149
150
151
/*
case MCH_STE:
masterclock=MASTERCLOCK_STE;
masterprediv=MASTERPREDIV_STE;
break;
*/
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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);
}
170
171
#if 1
172
173
174
175
176
177
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));
}
178
179
#endif
180
181
MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
182
183
DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
184
185
186
187
188
189
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));
190
191
return 0;
192
193
}
194
static void
195
MINTDMA8_InitAudio(_THIS)
196
{
197
198
199
200
201
202
203
204
205
void *oldpile;
unsigned long buffer;
unsigned char mode;
/* Set replay tracks */
if (cookie_snd & SND_16BIT) {
Settracks(0, 0);
Setmontracks(0);
}
206
207
oldpile = (void *) Super(0);
208
209
210
/* Stop currently playing sound */
DMAAUDIO_IO.control = 0;
211
212
213
214
215
216
/* 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;
217
218
219
220
221
buffer += SDL_MintAudio_audiosize;
DMAAUDIO_IO.end_high = (buffer >> 16) & 255;
DMAAUDIO_IO.end_mid = (buffer >> 8) & 255;
DMAAUDIO_IO.end_low = buffer & 255;
222
223
mode = 3 - MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
224
if (this->spec.channels == 1) {
225
226
227
mode |= 1 << 7;
}
DMAAUDIO_IO.sound_ctrl = mode;
228
229
230
231
232
/* Set interrupt */
Jdisint(MFP_DMASOUND);
Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
Jenabint(MFP_DMASOUND);
233
234
235
236
237
238
if (cookie_snd & SND_16BIT) {
if (Setinterrupt(SI_TIMERA, SI_PLAY) < 0) {
DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
}
}
239
240
241
/* Go */
DMAAUDIO_IO.control = 3; /* playback + repeat */
242
243
Super(oldpile);
244
245
}
246
static int
247
MINTDMA8_OpenDevice(_THIS, const char *devname, int iscapture)
248
{
249
SDL_MintAudio_device = this;
250
251
/* Check audio capabilities */
252
253
if (MINTDMA8_CheckAudio(this) == -1) {
return 0;
254
}
255
256
257
258
259
260
261
262
263
264
265
/* 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);
266
267
/* Allocate memory for audio buffers in DMA-able RAM */
268
DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
269
270
SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
271
if (SDL_MintAudio_audiobuf[0] == NULL) {
272
273
274
275
SDL_free(this->hidden);
this->hidden = NULL;
SDL_OutOfMemory();
return 0;
276
}
277
SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
278
SDL_MintAudio_numbuf = 0;
279
280
SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
SDL_MintAudio_audiosize = this->spec.size;
281
SDL_MintAudio_mutex = 0;
282
283
284
285
286
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]));
287
288
289
SDL_MintAudio_CheckFpu();
290
/* Setup audio hardware */
291
MINTDMA8_InitAudio(this);
292
293
return 1; /* good to go. */
294
}
295
296
297
298
299
300
301
302
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
335
336
337
338
339
340
341
342
static int
MINTDMA8_Init(SDL_AudioDriverImpl *impl)
{
/* 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;
impl->LockAudio = MINTDMA8_LockAudio;
impl->UnlockAudio = MINTDMA8_UnlockAudio;
impl->OnlyHasDefaultOutputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
impl->SkipMixerLock = 1;
return 1;
}
AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", MINTDMA8_Init, 0
};
343
/* vi: set ts=4 sw=4 expandtab: */