1 /* WARNING: As usual for performance reasons this library generally does not
2 * enable/disable interrupts (cli/sti). To avoid contention with
3 * interrupt handlers the calling program should do that. */
5 #include <hw/cpu/cpu.h>
8 #define SNDSB_MAX_CARDS 4
10 /* 0x2x0 + const = I/O port */
11 #define SNDSB_BIO_MIXER_INDEX 0x4
12 #define SNDSB_BIO_MIXER_DATA 0x5
13 #define SNDSB_BIO_DSP_RESET 0x6
14 #define SNDSB_BIO_DSP_READ_DATA 0xA
15 #define SNDSB_BIO_DSP_WRITE_DATA 0xC
16 #define SNDSB_BIO_DSP_WRITE_STATUS 0xC
17 #define SNDSB_BIO_DSP_READ_STATUS 0xE
18 #define SNDSB_BIO_DSP_READ_STATUS16 0xF
20 /* 0x3x0 + const = I/O port */
21 #define SNDSB_MPUIO_DATA 0x0
22 #define SNDSB_MPUIO_COMMAND 0x1
23 #define SNDSB_MPUIO_STATUS 0x1
26 #define SNDSB_DSPCMD_GET_VERSION 0xE1
29 #define SNDSB_MPUCMD_RESET 0xFF
30 #define SNDSB_MPUCMD_ENTER_UART 0x3F
34 SNDSB_MIXER_CT1345, /* Sound Blaster Pro chip */
35 SNDSB_MIXER_CT1745, /* Sound Blaster 16 */
39 /* which method to use when playing audio through the DSP */
41 SNDSB_DSPOUTMETHOD_DIRECT=0, /* DSP command 0x10 single-byte playback */
42 SNDSB_DSPOUTMETHOD_1xx, /* DSP command 0x14 8-bit mono (DSP 1.xx method) */
43 SNDSB_DSPOUTMETHOD_200, /* DSP command 0x1C 8-bit auto-init (DSP 2.00) */
44 SNDSB_DSPOUTMETHOD_201, /* DSP command 0x90 8-bit auto-init high speed (DSP 2.01+ using mixer bit to set stereo) */
45 SNDSB_DSPOUTMETHOD_3xx, /* DSP command 0x90 8-bit stereo auto-init (3.xx only) */
46 SNDSB_DSPOUTMETHOD_4xx, /* DSP command 0xBx/Cx 8/16-bit commands (DSP 4.xx) */
47 SNDSB_DSPOUTMETHOD_MAX
64 /* NOTES: The length is the amount of data the DSP will transfer, before signalling the ISR via the SB IRQ. Usually most programs
65 * will set this to an even subdivision of the total buffer size e.g. so that a 32KB playback buffer signals IRQ every 8KB.
66 * The Sound Blaster API will take care of programming the DMA controller with the physical memory address.
68 * If auto-init or DSP 4.xx commands are used, the library will try it's best but depending on the clone hardware it cannot
69 * guarantee that it can reprogram the physical memory address within the IRQ without causing one or two sample glitches,
70 * i.e. that the DSP will wait up for us when we mask DMA. In an ideal world the DSP will have a FIFO so that the time we
71 * spend DMA reprogramming is not an issue. It is said on true Creative SB16 hardware, that is precisely the case.
73 * Because the SB library has control, it will automatically subdivide submitted buffers if playback would cross a 64KB
74 * boundary. But, if the physical memory address is beyond the reach of your DMA controller, the library will skip your
75 * buffer and move on. This library will provide a convenience function to check for just that.
77 * Finally, remember that in 32-bit protected mode, linear addresses do not necessarily correspond to physical memory
78 * addresses. The DOS extender may be running in a DPMI environment that remaps memory. You will need to provide translation
79 * in that case. Keep in mind that when translating your linear address can be remapped in any order of physical pages, so
80 * you cannot convert just the base and assume the rest. Don't forget also that the DPMI server and environment may very well
81 * be paging memory to disk or otherwise moving it around. If you feed pages directly to this code, you must lock the pages.
82 * But if you are using DOS memory, the environment will most likely translate the DMA controller for you.
84 * In most cases, the best way to handle SB playback is to use the 8237 library to allocate a fixed DMA buffer (usually in
85 * lower DOS memory) and loop through that buffer in fragments, filling in behind the play pointer.
87 * the oplio variable is normally set to 0. if the Sound Blaster is Plug & Play compatible though, the OPL I/O port reported
88 * by ISA PnP will be placed there. This means that if your program wants to use the OPL3 FM synth, it should first check
89 * the oplio member and init the adlib library with that port. Else, it should assume port 0x388 and use that. Same rule
90 * applies to the gameio (gameport) member.
92 * The 'aweio' variable is meant to represent the wavetable section of
93 * the Sound Blaster AWE32 and AWE64 cards. It will be set by the ISA PnP
94 * code (since those cards are ISA PnP compliant) else it will be zero. */
97 uint16_t baseio,mpuio,oplio,gameio,aweio;
98 uint16_t wssio,opl3sax_controlio;
99 int8_t dma8,dma16,irq;
101 uint8_t audio_data_flipped_sign; /* DSP 4.xx command allows us to specify signed/unsigned */
102 uint8_t dsp_play_method;
103 uint8_t dsp_vmaj,dsp_vmin;
104 uint8_t dsp_ok,mixer_ok;
105 uint8_t dsp_stopping;
109 uint32_t buffer_size; /* length of the buffer IN BYTES */
110 uint32_t buffer_rate;
111 uint8_t buffer_16bit;
112 uint8_t buffer_stereo;
113 uint8_t buffer_hispeed;
114 uint32_t buffer_dma_started; /* for 1.xx modes: the DMA offset the transfer started */
115 uint32_t buffer_dma_started_length; /* ...and for how long */
116 volatile uint32_t direct_dsp_io; /* for direct DAC/ADC mode: software I/O pointer */
117 uint32_t buffer_irq_interval; /* samples per IRQ. The DSP will be instructed to play this many samples, then signal the IRQ. */
118 /* ADPCM modes: This becomes "bytes per IRQ" which depending on the ADPCM encoding can be 1/2, 1/3, or 1/4 the sample count. The first ADPCM block is expected to have the reference byte. */
119 /* Sound blaster 1.0 and 2.0: Short intervals may cause playback to audibly pop and stutter, since DSP playback requires reprogramming per block */
120 volatile uint32_t buffer_last_io; /* EXTERNAL USE: where the calling program last wrote/read the buffer. prepare_dma sets this to zero, but program maintains it */
121 unsigned char FAR* buffer_lin; /* linear (program accessible pointer) */
122 uint32_t buffer_phys;
123 char dsp_copyright[128];
124 /* adjustment for known weird clones of the SB chipset */
125 uint8_t is_gallant_sc6600:1; /* Reveal/Gallant SC6600: DSP v3.5 but supports SB16 commands except for the mixer register configuration stuff */
126 uint8_t enable_adpcm_autoinit:1;/* Most emulators including DOSBox do not emulate auto-init ADPCM playback */
127 uint8_t mega_em:1; /* Gravis MEGA-EM detected, tread very very carefully */
128 uint8_t sbos:1; /* Gravis SBOS */
129 /* options for calling library */
130 uint8_t goldplay_mode:1; /* Goldplay mode: Set DMA transfer length to 1 (2 if stereo) and overwrite the same region of memory from timer.
131 An early tracker/sound library released in 1991 called Goldplay does just that, which is why
132 stuff from the demoscene using that library has compatibility issued on today's hardware.
134 uint8_t dsp_autoinit_dma:1; /* in most cases, you can just setup the DMA buffer to auto-init loop
135 and then re-issue the playback command as normal. But some emulations,
136 especially Gravis UltraSound SBOS/MEGA-EM, don't handle that too well.
137 the only way to play properly with them is to NOT do auto-init DMA
138 and to set the DSP block size & DMA count to only precisely the IRQ
139 interval. In which case, set this to 0 */
140 uint8_t dsp_autoinit_command:1; /* whether or not to use the auto-init form of playback/recording */
141 uint8_t dosbox_emulation:1; /* we're running from within DOSBox */
142 uint8_t virtualbox_emulation:1; /* we're running from within Sun/Oracle Virtualbox */
143 uint8_t windows_emulation:1; /* we're running under Windows where the implementation is probably shitty */
144 uint8_t windows_xp_ntvdm:1; /* Microsoft's NTVDM.EXE based emulation in Windows XP requires some restrictive
145 workarounds to buffer size, interval, etc. to work properly. Note this also
146 applies to Windows Vista. */
147 uint8_t dsp_alias_port:1; /* if set, use DSP alias I/O port 0x22D (SB DSP 1.x and 2.x only!) EMF_ID style */
148 uint8_t backwards:1; /* play buffer in reverse. will instruct DMA controller to decrement addr */
149 uint8_t windows_9x_me_sbemul_sys:1;/* Microsoft's SBEMUL.SYS driver, Windows 98/ME */
150 uint8_t windows_creative_sb16_drivers:1;/* Creative Sound Blaster 16 drivers for Windows */
151 uint8_t vdmsound:1; /* We're running under VDMSOUND.EXE */
152 uint8_t do_not_probe_irq:1; /* if the card has known configuration registers, then do not probe */
153 uint8_t do_not_probe_dma:1; /* ... */
154 uint8_t ess_extensions:1; /* use ESS 688/1869 extended commands */
155 uint8_t force_hispeed:1; /* always use highspeed DSP playback commands (except for DSP 4.xx) */
156 uint8_t dsp_4xx_fifo_autoinit:1; /* SB16 use FIFO for auto-init playback */
157 uint8_t dsp_4xx_fifo_single_cycle:1; /* SB16 use FIFO for single-cycle playback */
158 uint8_t dsp_nag_mode:1; /* "Nag" the DSP during playback (Crystal Dream style) by reissuing playback while playback is active */
159 uint8_t dsp_nag_hispeed:1; /* "Nag" even during highspeed DMA playback (NOT recommended) */
160 uint8_t poll_ack_when_no_irq:1; /* If playing DMA without IRQ assignment, poll the "ack" register in idle call */
161 uint8_t hispeed_matters:1; /* If set, playing at rates above 22050Hz requires hispeed DSP commands */
162 uint8_t hispeed_blocking:1; /* DSP does not accept commands, requires reset, in hispeed DSP playback */
163 uint8_t dsp_direct_dac_read_after_command; /* read the DSP write status N times after direct DAC commands */
164 uint8_t dsp_direct_dac_poll_retry_timeout; /* poll DSP write status up to N times again before attempting DSP command */
165 const char* reason_not_supported; /* from last call can_do() or is_supported() */
166 /* array of mixer controls, determined by mixer chipset */
167 struct sndsb_mixer_control* sb_mixer;
168 signed short sb_mixer_items;
169 /* max sample rate of the DSP */
170 unsigned short max_sample_rate_dsp4xx; /* in Hz, maximum per sample frame */
171 unsigned short max_sample_rate_sb_hispeed; /* in Hz, maximum per sample i.e. DSP maxes out at this value at mono, or half this value at stereo */
172 unsigned short max_sample_rate_sb_hispeed_rec; /* in Hz, maximum per sample i.e. DSP maxes out at this value at mono, or half this value at stereo */
173 unsigned short max_sample_rate_sb_play; /* in Hz, maximum playback rate in non-hispeed mode */
174 unsigned short max_sample_rate_sb_rec; /* in Hz, maximum recording rate in non-hispeed mode */
175 unsigned short max_sample_rate_sb_play_dac; /* in Hz, maximum playback rate through DSP command 0x10 (Direct DAC output) */
176 unsigned short max_sample_rate_sb_rec_dac; /* in Hz, maximum recording rate through DSP command 0x20 (Direct DAC input) */
177 /* function call. calling application should call this from the timer interrupt (usually IRQ 0) to
178 * allow direct DAC and "goldplay" modes to work or other idle maintenance functions. if NULL, do not call. */
179 void (*timer_tick_func)(struct sndsb_ctx *cx);
180 /* goldplay mode DMA buffer */
181 #if TARGET_MSDOS == 32
182 struct dma_8237_allocation* goldplay_dma;
184 uint8_t goldplay_dma[4];
187 /* ISA PnP information */
188 const char* pnp_name;
190 uint8_t pnp_csn; /* PnP Card Select Number */
191 uint8_t pnp_bios_node; /* PnP BIOS device node (0xFF if none) */
192 uint8_t ess_chipset; /* which ESS chipset */
193 /* Windows compat hack */
194 uint16_t windows_creative_sb16_drivers_ver;
195 uint8_t windows_springwait; /* when windows_emulation == 1, defer actually starting a DSP block until
196 the calling program has a chance to fill the buffer and check the position.
197 assume the emulation provided by Windows is the kind that (more or less)
198 directly converts DSP block commands to waveOutWrite() calls or some
199 nonsense, therefore tracking the DMA pointer and writing to the buffer
200 behind it will only cause audio glitches. Note that the test program's
201 order of calls are incompatible with Windows in this way: setting up the
202 DSP first and then setting up DMA only confuses the emulation. Doing this
203 effectively defers DSP programming until after the host program has set up
204 DMA, ensuring the minimalist emulation provided by Windows is not confused. */
205 uint8_t chose_autoinit_dma:1; /* the library chooses to use autoinit DMA */
206 uint8_t chose_autoinit_dsp:1; /* the library chooses to use auto-init commands */
207 uint8_t chose_use_dma:1; /* the library chooses to run in a manner that uses DMA */
208 uint8_t direct_dac_sent_command:1; /* direct DSP playback: we just sent the command, next is data */
209 uint8_t ess_extended_mode:1; /* if set, ESS chip is in extended mode */
210 uint8_t timer_tick_signal:1;
213 /* runtime "options" that affect sound blaster probing.
214 * note that they are only advisory flags to the library.
215 * all flags are initialized to zero even prior to init_sndsb() */
216 struct sndsb_probe_opts {
217 unsigned char disable_manual_irq_probing:1; /* don't use hardcore manual IRQ probing /nomirqp */
218 unsigned char disable_alt_irq_probing:1; /* don't use alt "lite" IRQ probing /noairqp */
219 unsigned char disable_sb16_read_config_byte:1; /* don't read configuration from SB16 mixer byte /nosb16cfg */
220 unsigned char disable_manual_dma_probing:1; /* don't probe for DMA channel if unknown /nodmap */
221 unsigned char disable_manual_high_dma_probing:1; /* don't probe for 16-bit DMA channel if unknown /nohdmap */
222 unsigned char disable_windows_vxd_checks:1; /* don't try to identify Windows drivers /nowinvxd */
223 unsigned char disable_ess_extensions:1; /* don't use/detect ESS688/ESS1869 commands /noess */
224 unsigned char experimental_ess:1; /* use ESS extensions even on chips not yet supported /ex-ess */
225 unsigned char use_dsp_alias:1; /* probe, initialize and default to alias 22Dh /sbalias:dsp */
228 extern struct sndsb_probe_opts sndsb_probe_options;
230 #if TARGET_MSDOS == 32
231 extern signed char sndsb_nmi_32_hook;
234 #if TARGET_MSDOS == 32 && !defined(TARGET_WINDOWS)
235 /* TODO: This should be moved into the hw/DOS library */
236 extern unsigned char nmi_32_hooked;
237 extern void (interrupt *nmi_32_old_vec)();
240 struct sndsb_mixer_control {
242 unsigned char offset:4;
243 unsigned char length:4;
247 extern const char *sndsb_dspoutmethod_str[SNDSB_DSPOUTMETHOD_MAX];
248 extern const char *sndsb_mixer_chip_name[SNDSB_MIXER_MAX];
249 extern struct sndsb_ctx sndsb_card[SNDSB_MAX_CARDS];
250 extern signed char gallant_sc6600_map_to_dma[4];
251 extern signed char gallant_sc6600_map_to_irq[8];
252 extern const char* sndsb_adpcm_mode_str[4];
253 extern struct sndsb_ctx *sndsb_card_blaster;
254 extern int sndsb_card_next;
256 struct sndsb_ctx *sndsb_by_base(uint16_t x);
257 struct sndsb_ctx *sndsb_by_mpu(uint16_t x);
258 struct sndsb_ctx *sndsb_by_irq(int8_t x);
259 struct sndsb_ctx *sndsb_by_dma(uint16_t x);
260 struct sndsb_ctx *sndsb_alloc_card();
263 void sndsb_free_card(struct sndsb_ctx *c);
264 struct sndsb_ctx *sndsb_try_blaster_var();
265 const char *sndsb_mixer_chip_str(uint8_t c);
266 int sndsb_read_dsp(struct sndsb_ctx *cx);
267 int sndsb_read_dsp_timeout(struct sndsb_ctx *cx,unsigned long timeout_ms);
268 int sndsb_reset_dsp(struct sndsb_ctx *cx);
269 int sndsb_read_mixer(struct sndsb_ctx *cx,uint8_t i);
270 void sndsb_write_mixer(struct sndsb_ctx *cx,uint8_t i,uint8_t d);
271 int sndsb_probe_mixer(struct sndsb_ctx *cx);
272 int sndsb_mpu_command(struct sndsb_ctx *cx,uint8_t d);
273 int sndsb_mpu_write(struct sndsb_ctx *cx,uint8_t d);
274 int sndsb_mpu_read(struct sndsb_ctx *cx);
275 int sndsb_probe_mpu401(struct sndsb_ctx *cx);
276 int sndsb_write_dsp(struct sndsb_ctx *cx,uint8_t d);
277 int sndsb_write_dsp_timeout(struct sndsb_ctx *cx,uint8_t d,unsigned long timeout_ms);
278 int sndsb_write_dsp_timeconst(struct sndsb_ctx *cx,uint8_t tc);
279 int sndsb_query_dsp_version(struct sndsb_ctx *cx);
280 int sndsb_init_card(struct sndsb_ctx *cx);
281 int sndsb_try_base(uint16_t iobase);
282 int sndsb_interrupt_reason(struct sndsb_ctx *cx);
283 int sndsb_reset_mixer(struct sndsb_ctx *cx);
284 int sndsb_dsp_out_method_supported(struct sndsb_ctx *cx,unsigned long wav_sample_rate,unsigned char wav_stereo,unsigned char wav_16bit);
285 int sndsb_write_dsp_blocksize(struct sndsb_ctx *cx,uint16_t tc);
286 int sndsb_write_dsp_outrate(struct sndsb_ctx *cx,unsigned long rate);
287 uint32_t sndsb_read_dma_buffer_position(struct sndsb_ctx *cx);
288 int sndsb_shutdown_dma(struct sndsb_ctx *cx);
289 int sndsb_setup_dma(struct sndsb_ctx *cx);
290 int sndsb_prepare_dsp_playback(struct sndsb_ctx *cx,unsigned long rate,unsigned char stereo,unsigned char bit16);
291 int sndsb_begin_dsp_playback(struct sndsb_ctx *cx);
292 int sndsb_stop_dsp_playback(struct sndsb_ctx *cx);
293 void sndsb_send_buffer_again(struct sndsb_ctx *cx);
294 int sndsb_determine_ideal_dsp_play_method(struct sndsb_ctx *cx);
295 void sndsb_choose_mixer(struct sndsb_ctx *card,signed char override);
296 int sndsb_submit_buffer(struct sndsb_ctx *cx,unsigned char FAR *ptr,uint32_t phys,uint32_t len,uint32_t user,uint8_t loop);
297 int sndsb_assign_dma_buffer(struct sndsb_ctx *cx,struct dma_8237_allocation *dma);
298 unsigned char sndsb_rate_to_time_constant(struct sndsb_ctx *cx,unsigned long rate);
299 unsigned int sndsb_ess_set_extended_mode(struct sndsb_ctx *cx,int enable);
300 int sndsb_ess_read_controller(struct sndsb_ctx *cx,int reg);
301 int sndsb_ess_write_controller(struct sndsb_ctx *cx,int reg,unsigned char value);
302 void sndsb_irq_continue(struct sndsb_ctx *cx,unsigned char c);
303 unsigned int sndsb_will_dsp_nag(struct sndsb_ctx *cx);
305 int sb_nmi_32_auto_choose_hook();
306 #if TARGET_MSDOS == 32
307 void do_nmi_32_unhook();
308 void do_nmi_32_hook();
310 # define do_nmi_32_unhook()
311 # define do_nmi_32_hook()
314 static inline unsigned char sndsb_ctx_to_index(struct sndsb_ctx *c) {
315 return (unsigned char)(((size_t)c - (size_t)sndsb_card) / sizeof(struct sndsb_ctx));
318 static inline struct sndsb_ctx *sndsb_index_to_ctx(unsigned char c) {
319 return sndsb_card + c;
322 static inline int sndsb_recommend_vm_wait(struct sndsb_ctx *cx) {
323 /* Microsoft Windows XP and NTVDM.EXE Sound Blaster emulation:
324 * - Emulation is terrible. Audio can skip and stutter slightly.
325 * Giving up your timeslice only guarantees it will stutter a lot *WORSE* */
326 if (cx->windows_emulation && cx->windows_xp_ntvdm) return 0;
328 /* Microsoft Windows XP and VDMSOUND. Yielding is recommended,
329 * but you will get very stuttery sound with small block sizes! */
330 if (cx->windows_emulation && cx->buffer_irq_interval < (cx->buffer_rate/4)) return 0;
332 /* otherwise, yes. go ahead */
336 static inline void sndsb_interrupt_ack(struct sndsb_ctx *cx,unsigned char c) {
337 if (c & 1) inp(cx->baseio + SNDSB_BIO_DSP_READ_STATUS);
338 if (c & 2) inp(cx->baseio + SNDSB_BIO_DSP_READ_STATUS16);
341 static inline void sndsb_dsp_direct_output(struct sndsb_ctx *cx,unsigned char c) {
342 sndsb_write_dsp(cx,0x10);
343 sndsb_write_dsp(cx,c);
346 void sndsb_main_idle(struct sndsb_ctx *cx);
348 /* Sound Blaster ADPCM encoding routines */
349 #if TARGET_MSDOS == 16 && (defined(__COMPACT__) || defined(__SMALL__))
351 unsigned char sndsb_encode_adpcm_4bit(unsigned char samp);
352 unsigned char sndsb_encode_adpcm_2bit(unsigned char samp);
353 unsigned char sndsb_encode_adpcm_2_6bit(unsigned char samp,unsigned char b2);
354 void sndsb_encode_adpcm_set_reference(unsigned char c,unsigned char mode);
355 void sndsb_encode_adpcm_reset_wo_ref(unsigned char mode);
356 void sndsb_alt_lite_probe_irq(struct sndsb_ctx *cx);
357 void sndsb_manual_probe_irq(struct sndsb_ctx *cx);
358 void sndsb_manual_probe_dma(struct sndsb_ctx *cx);
361 void sndsb_write_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc,unsigned char nb);
362 unsigned char sndsb_read_mixer_entry(struct sndsb_ctx *sb,struct sndsb_mixer_control *mc);
363 unsigned long sndsb_real_sample_rate(struct sndsb_ctx *cx);
365 uint32_t sndsb_recommended_dma_buffer_size(struct sndsb_ctx *ctx,uint32_t limit);
367 void sndsb_timer_tick_directi_data(struct sndsb_ctx *cx);
368 void sndsb_timer_tick_directi_cmd(struct sndsb_ctx *cx);
369 void sndsb_timer_tick_directo_data(struct sndsb_ctx *cx);
370 void sndsb_timer_tick_directo_cmd(struct sndsb_ctx *cx);
372 const char *sndsb_ess_chipset_str(unsigned int c);
374 #if TARGET_MSDOS == 32
375 int sb_nmi_32_auto_choose_hook();