]> 4ch.mooo.com Git - 16.git/blob - 16/PCGPE10/SBDSP.TXT
modified: 16/modex16/scroll.c
[16.git] / 16 / PCGPE10 / SBDSP.TXT
1 \r
2                   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
3                   ³ Programming the SoundBlaster DSP ³\r
4                   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
5 \r
6                   Written for the PC-GPE by Mark Feldman\r
7               e-mail address : u914097@student.canberra.edu.au\r
8                                myndale@cairo.anu.edu.au\r
9 \r
10              ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
11              ³      THIS FILE MAY NOT BE DISTRIBUTED     ³\r
12              ³ SEPARATE TO THE ENTIRE PC-GPE COLLECTION. ³\r
13              ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
14 \r
15 \r
16 ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
17 ³ Disclaimer ³\r
18 ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
19 \r
20 I assume no responsibility whatsoever for any effect that this file, the\r
21 information contained therein or the use thereof has on you, your sanity,\r
22 computer, spouse, children, pets or anything else related to you or your\r
23 existance. No warranty is provided nor implied with this information.\r
24 \r
25 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
26 ³ Introduction ³\r
27 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
28 \r
29 The SoundBlaster is capable of both FM and digitised sounds. The FM wave\r
30 is fully Adlib compatible, so check the ADLIB.TXT file for info\r
31 on how to program it. This file will concentrate on recording and playback\r
32 of digital samples through the SoundBlaster CT-DSP 1321 chip.\r
33 \r
34 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
35 ³ The SoundBlaster DSP I/O Ports ³\r
36 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
37 \r
38 The DSP (Digital Sound Processor) chip is programmed through 4 ports which\r
39 are determined by the SoundBlaster base address jumper setting:\r
40 \r
41                     RESET    2x6h\r
42 \r
43                 READ DATA    2xAh\r
44 \r
45 WRITE COMMAND/DATA output\r
46 WRITE BUFFER STATUS input    2xCh\r
47 \r
48 \r
49            DATA AVAILABLE    2xEh\r
50 \r
51 where x = 1 for base address jumper setting 210h\r
52       x = 2 for base address jumper setting 220h\r
53       .\r
54       .\r
55       x = 6 for base address jumper setting 260h\r
56 \r
57 \r
58 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
59 ³ Resetting the DSP ³\r
60 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
61 \r
62 You have to reset the DSP before you program it. This is done with the\r
63 following procedure :\r
64 \r
65 1) Write a 1 to the SoundBlaster RESET port (2x6h)\r
66 2) Wait for 3 micro-seconds\r
67 3) Write a 0 to the SoundBlaster RESET port (2x6h)\r
68 4) Read the byte from the DATA AVAILABLE (2xEh) port until bit 7 = 1\r
69 5) Poll for a ready byte (AAh) from the READ DATA port (2xAh). Before\r
70    reading the READ DATA port it is avdvisable.\r
71 \r
72 The DSP usually takes somewhere around 100 micro-seconds to reset itself.\r
73 If it fails to do within a reasonable time (say 200 micro-seconds) then\r
74 an error has occurred, possibly an incorrect I/O address is being used.\r
75 \r
76 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
77 ³ Writing to the DSP ³\r
78 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
79 \r
80 A value can be written to the DSP with the following procedure :\r
81 \r
82 1) Read the DSP's WRITE BUFFER STATUS port (2xCh) until bit 7 = 0\r
83 2) Write the value to the WRITE COMMAND/DATA port (2xCh)\r
84 \r
85 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
86 ³ Reading the DSP ³\r
87 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
88 \r
89 A value can be read from the DSP with the following procedure :\r
90 \r
91 1) Read the DSP's DATA AVAILABLE port (2xEh) until bit 7 = 1\r
92 2) Read the data from the READ DATA port (2xAh)\r
93 \r
94 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
95 ³ Turning the speaker on and controlling DMA ³\r
96 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
97 \r
98 Speaker and DMA control are handled by writing one of the following bytes\r
99 to the DSP:\r
100 \r
101                      ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
102                      ³ Value   Description     ³\r
103                      ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\r
104                      ³ D0h    DMA Stop         ³\r
105                      ³ D1h    Turn speaker on  ³\r
106                      ³ D3h    Turn speaker off ³\r
107                      ³ D4h    DMA Continue     ³\r
108                      ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
109 \r
110 DMA is discussed below. The DMA commands shown here can be used to pause\r
111 the sample during DMA playback playback.\r
112 \r
113 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
114 ³ Writing to the DAC ³\r
115 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
116 \r
117 The DAC (Digital to Analog Converter) is the part of the card which converts\r
118 a sample number (ie 0 -> 255) to a sound level. To generate a square sound\r
119 wave at maximum volume (for example) you could alternate writing 0's and\r
120 255's to the DAC.\r
121 \r
122 Programming the DAC in direct mode involves the main program setting the\r
123 DAC to a desired value. Only 8 bit DAC is available in direct mode. To set\r
124 the DAC level you write the value 10h to the DSP followed by the sample\r
125 number (0 -> 255). Note that no sound will be heard unless the speaker has\r
126 been turned on. In direct mode the main program is responsible for the\r
127 timing between samples, the DAC can output sound samples as fast as the\r
128 calling program can change it. Typically the timer interrupt is reprogrammed\r
129 and used to generate the timing required for a sample playback. Info on\r
130 programming the PIT chip can be found in the PIT.TXT file.\r
131 \r
132 The DAC can also be programmed to accept values sent to it via the DMA\r
133 chip. Draeden has written an excellent article on programming the DMA chip\r
134 (see DMA_VLA.TXT) so only a brief example of it's use will be given here.\r
135 The important thing to remember is that the DMA chip cannot transfer data\r
136 which crosses between page breaks. If the data does cross page breaks then\r
137 it will have to be split up into several transfers, with one page per\r
138 transfer.\r
139 \r
140 Setting the playback frequency for the DMA transfer is done by writing\r
141 the value 40h to the DSP followed by TIME_CONSTANT, where\r
142 TIME_CONSTANT = 256 - 1000000 / frequency\r
143 \r
144 There are several types of DMA transfers available. The following table\r
145 lists them:\r
146 \r
147       ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
148       ³DMA_TYPE_VALUE   Description             Frequency Range    ³\r
149       ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\r
150       ³    14h          8 bit                   4KHz -> 23 KHz     ³\r
151       ³    74h          4 bit ADPCM             4KHz -> 12 KHz     ³\r
152       ³    75h          4 bit ADPCM with        4KHz -> 12 KHz     ³\r
153       ³                 reference byte                             ³\r
154       ³    76h          2.6 bit ADPCM           4KHz -> 13 KHz     ³\r
155       ³    77h          2.6 bit ADPCM with      4KHz -> 13 KHz     ³\r
156       ³                 reference byte                             ³\r
157       ³    16h          2 bit ADPCM             4KHz -> 11 KHz     ³\r
158       ³    17h          2 bit ADPCM with        4KHz -> 11 KHz     ³\r
159       ³                 reference byte                             ³\r
160       ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
161 \r
162 ADPCM stands for Adaptive Pulse Code Modulation, a sound compression\r
163 technique where the difference between successive samples is stored rather\r
164 than their actual values. In the modes with reference bytes, the first\r
165 byte is the actual starting value. Having modes with and without reference\r
166 bytes means you can output successive blocks without the need for a\r
167 reference byte at the start of each one.\r
168 \r
169 The procedure for doing a DMA transfer is as follows:\r
170 \r
171 1) Load the sound data into memory\r
172 2) Set up the DMA chip for the tranfer\r
173 3) Set the DSP TIME_CONSTANT to the sampling rate\r
174 4) Write DMA_TYPE_VALUE value to the DSP\r
175 5) Write DATA_LENGTH to the DSP (2 bytes, LSB first) where\r
176    DATA_LENGTH = number of bytes to send - 1\r
177 \r
178 Note that the DMA chip must be programmed before the BSP.\r
179 \r
180 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
181 ³ Reading from the ADC ³\r
182 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
183 \r
184 Reading samples from the ADC (Analog to Digital Converter) can also be\r
185 done in either direct or DMA mode.\r
186 \r
187 To read a sample in direct mode write the value 20h to the DSP and then\r
188 read the value from the DSP. Simple as that!\r
189 \r
190 To set up the DSP for a DMA transfer, follow this procedure :\r
191 \r
192 1) Get a memory buffer ready to hold the sample\r
193 2) Set up the DMA chip for the transfer\r
194 3) Set the DSP TIME_CONSTANT to the sampling rate\r
195 4) Write the value 24h to the DSP\r
196 5) Write DATA_LENGTH to the DSP (2 bytes, LSB first) where\r
197    DATA_LENGTH = number of bytes to read - 1\r
198 \r
199 Note that the DMA chip must be programmed before the BSP.\r
200 \r
201 DMA reads only support 8 bit mode, compressed modes are done by software and\r
202 stored in the voc file. I haven't tried to figure out how the compression is\r
203 done. If someone does figure it out I'd like to know about it!\r
204 \r
205 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
206 ³ Programming the DMA Chip ³\r
207 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
208 \r
209 As mentioned before, Draeden has written a very good article on the dma\r
210 chip, but here is a brief run down on what you would need to do to program\r
211 the DMA channel 1 for the DSP in real mode:\r
212 \r
213 1) Calculate the 20 bit address of the memory buffer you are using\r
214    where Base Address = Segment * 16 + Offset\r
215    eg 1234h:5678h = 179B8h\r
216 2) Send the value 05h to port 0Ah (mask off channel 1)\r
217 3) Send the value 00h to port 0Ch (clear the internal DMA flip/flop)\r
218 4) Send the value 49h to port 0Bh (for playback) or\r
219                   45h to port 0Bh (for recording)\r
220 5) Write the LSB (bits 0 -> 7) of the 20 bit memory address to port 02h\r
221 6) Write the MSB (bits 8 -> 15) of the 20 bit memory address to ort 02h\r
222 7) Write the Page (bits 16 -> 19) of the 20 bit memory address to port 83h\r
223 8) Send the LSB of DATA_LENGTH to port 03h\r
224 9) Send the MSB of DATA_LENGTH to port 03h\r
225 10) Send the value 01h to port 0Ah (enable channel 1)\r
226 \r
227 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
228 ³ End of DMA Interrupt ³\r
229 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
230 \r
231 When a DMA transfer is complete an interrupt is generated. The actual\r
232 interrupt number depends on the SoundBlaster card's IRQ jumper setting:\r
233 \r
234                          ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
235                          ³ IRQ Jumper             ³\r
236                          ³  Setting     Interrupt ³\r
237                          ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´\r
238                          ³    2            0Ah    ³\r
239                          ³    3            0Bh    ³\r
240                          ³    5            0Dh    ³\r
241                          ³    7            0Fh    ³\r
242                          ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
243 \r
244 To service one of these interrupts you must perform these 3 tasks:\r
245 \r
246 1) Acknowledge the DSP interrupt by reading the DATA AVAILABLE port (2xEh)\r
247    once.\r
248 2) If there are more blocks to transfer then set them up\r
249 3) Output value 20h (EOI) to the interrupt controller port 20h\r
250 \r
251 Of course, as with any hardware interrupt you must also leave the\r
252 state of the system (registers etc..) the way it was when the interrupt\r
253 was called.\r
254 \r
255 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
256 ³ A Simple DSP Pascal Unit ³\r
257 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
258 \r
259 {\r
260 \r
261   DSP.PAS - A demo SoundBlaster DSP unit for real mode\r
262 \r
263   By Mark Feldman\r
264 }\r
265 \r
266 Unit DSP;\r
267 \r
268 Interface\r
269 \r
270 { ResetDSP returns true if reset was successful\r
271   base should be 1 for base address 210h, 2 for 220h etc... }\r
272 function ResetDSP(base : word) : boolean;\r
273 \r
274 { Write DAC sets the speaker output level }\r
275 procedure WriteDAC(level : byte);\r
276 \r
277 { ReadDAC reads the microphone input level }\r
278 function ReadDAC : byte;\r
279 \r
280 { SpeakerOn connects the DAC to the speaker }\r
281 function SpeakerOn: byte;\r
282 \r
283 { SpeakerOff disconnects the DAC from the speaker,\r
284   but does not affect the DAC operation }\r
285 function SpeakerOff: byte;\r
286 \r
287 { Functions to pause DMA playback }\r
288 procedure DMAStop;\r
289 procedure DMAContinue;\r
290 \r
291 { Playback plays a sample of a given size back at a given frequency using\r
292   DMA channel 1. The sample must not cross a page boundry }\r
293 procedure Playback(sound : Pointer; size : word; frequency : word);\r
294 \r
295 Implementation\r
296 \r
297 Uses Crt;\r
298 \r
299 var      DSP_RESET : word;\r
300      DSP_READ_DATA : word;\r
301     DSP_WRITE_DATA : word;\r
302   DSP_WRITE_STATUS : word;\r
303     DSP_DATA_AVAIL : word;\r
304 \r
305 function ResetDSP(base : word) : boolean;\r
306 begin\r
307 \r
308   base := base * $10;\r
309 \r
310   { Calculate the port addresses }\r
311   DSP_RESET := base + $206;\r
312   DSP_READ_DATA := base + $20A;\r
313   DSP_WRITE_DATA := base + $20C;\r
314   DSP_WRITE_STATUS := base + $20C;\r
315   DSP_DATA_AVAIL := base + $20E;\r
316 \r
317   { Reset the DSP, and give some nice long delays just to be safe }\r
318   Port[DSP_RESET] := 1;\r
319   Delay(10);\r
320   Port[DSP_RESET] := 0;\r
321   Delay(10);\r
322   if (Port[DSP_DATA_AVAIL] And $80 = $80) And\r
323      (Port[DSP_READ_DATA] = $AA) then\r
324     ResetDSP := true\r
325   else\r
326     ResetDSP := false;\r
327 end;\r
328 \r
329 procedure WriteDSP(value : byte);\r
330 begin\r
331   while Port[DSP_WRITE_STATUS] And $80 <> 0 do;\r
332   Port[DSP_WRITE_DATA] := value;\r
333 end;\r
334 \r
335 function ReadDSP : byte;\r
336 begin\r
337   while Port[DSP_DATA_AVAIL] and $80 = 0 do;\r
338   ReadDSP := Port[DSP_READ_DATA];\r
339 end;\r
340 \r
341 procedure WriteDAC(level : byte);\r
342 begin\r
343   WriteDSP($10);\r
344   WriteDSP(level);\r
345 end;\r
346 \r
347 function ReadDAC : byte;\r
348 begin\r
349   WriteDSP($20);\r
350   ReadDAC := ReadDSP;\r
351 end;\r
352 \r
353 function SpeakerOn: byte;\r
354 begin\r
355   WriteDSP($D1);\r
356 end;\r
357 \r
358 function SpeakerOff: byte;\r
359 begin\r
360   WriteDSP($D3);\r
361 end;\r
362 \r
363 procedure DMAContinue;\r
364 begin\r
365   WriteDSP($D4);\r
366 end;\r
367 \r
368 procedure DMAStop;\r
369 begin\r
370   WriteDSP($D0);\r
371 end;\r
372 \r
373 procedure Playback(sound : Pointer; size : word; frequency : word);\r
374 var time_constant : word;\r
375      page, offset : word;\r
376 begin\r
377 \r
378   SpeakerOn;\r
379 \r
380   size := size - 1;\r
381 \r
382   { Set up the DMA chip }\r
383   offset := Seg(sound^) Shl 4 + Ofs(sound^);\r
384   page := (Seg(sound^) + Ofs(sound^) shr 4) shr 12;\r
385   Port[$0A] := 5;\r
386   Port[$0C] := 0;\r
387   Port[$0B] := $49;\r
388   Port[$02] := Lo(offset);\r
389   Port[$02] := Hi(offset);\r
390   Port[$83] := page;\r
391   Port[$03] := Lo(size);\r
392   Port[$03] := Hi(size);\r
393   Port[$0A] := 1;\r
394 \r
395   { Set the playback frequency }\r
396   time_constant := 256 - 1000000 div frequency;\r
397   WriteDSP($40);\r
398   WriteDSP(time_constant);\r
399 \r
400   { Set the playback type (8-bit) }\r
401   WriteDSP($14);\r
402   WriteDSP(Lo(size));\r
403   WriteDSP(Hi(size));\r
404 end;\r
405 \r
406 end.\r
407 \r
408 \r
409 ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
410 ³ References ³\r
411 ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
412 \r
413 Title : The SoundBlaster Developpers Kit\r
414 Publishers : Creative Labs Inc\r
415              Creative Technology PTE LTD\r
416 \r
417 Title : Sound Blaster - The Official Book\r
418 Authors : Richard Heimlich, David M. Golden, Ivan Luk, Peter M. Ridge\r
419 Publishers : Osborne/McGraw Hill\r
420 ISBN : 0-07-881907-5\r
421 \r
422 Some of the information in this file was either obtained from or verified\r
423 by the source code in a public domain library called SOUNDX by Peter\r
424 Sprenger. I haven't tried using his library yet (I don't have a C compiler\r
425 at the moment) but it looks very well done and contains numerous sound card\r
426 detection routines. Says Peter : "It would be nice, that when you make\r
427 something commercial with my routines, that you send me a copy of your\r
428 project or send me some bucks, just enough for pizza and coke to support my\r
429 night programming sessions. If you send me nothing, ok. But USE the stuff,\r
430 if you can need it!". Heh...a REAL programmer!\r
431 \r
432 ftpsite: ftp.uwp.edu\r
433 directory: /pub/msdos/demos/programming/game-dev/source\r
434 filename: soundx.zip\r
435 \r
436 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
437 ³ Sound Familiar? ³\r
438 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
439 \r
440 What the...why is there a faint glimmer of sunlight outside? HOLY $#!^!! It's\r
441 5:30am! I'm goin' to bed!\r
442 \r