]> icculus.org git repositories - btb/d2x.git/blob - unused/bios/rbaudio.new
This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / unused / bios / rbaudio.new
1 /*\r
2  * $Source: /cvs/cvsroot/d2x/unused/bios/rbaudio.new,v $\r
3  * $Revision: 1.1.1.1 $\r
4  * $Author: bradleyb $\r
5  * $Date: 2001-01-19 03:30:14 $\r
6  *\r
7  * Redbook Audio Library  \r
8  *\r
9  * $Log: not supported by cvs2svn $\r
10  * Revision 1.18  1996/04/15  15:27:40  samir\r
11  * Play multiple tracks and PeekPlayStatus uses timer method!\r
12  * \r
13  * Revision 1.17  1996/04/12  20:08:42  samir\r
14  * Added debugging info and Redbook / HSG detection\r
15  * \r
16  * Revision 1.16  1996/04/12  19:13:29  matt\r
17  * Changed parameter name and added comments\r
18  * \r
19  * Revision 1.15  1996/04/12  18:08:02  samir\r
20  * We now pass a cd drive letter to RBAInit.\r
21  * \r
22  * Revision 1.14  1996/02/14  13:31:29  samir\r
23  * Fixed stupid bug that caused last track to never be played\r
24  * \r
25  * Revision 1.13  1996/02/13  17:16:04  samir\r
26  * Added Pause and Resume Caps.\r
27  * \r
28  * Revision 1.12  1996/01/11  10:08:01  matt\r
29  * RBARegisterCD wasn't checking SendRequest error code, so it was reporting\r
30  * CD tracks when there was no CD in the drive.\r
31  * \r
32  * Revision 1.11  1996/01/10  20:15:45  samir\r
33  * Changed behavior of RBACheckMediaChange to work\r
34  * correctly, as well as calling this function in critical\r
35  * RBA functions to take care of CD changes.\r
36  * \r
37  * Revision 1.10  1996/01/10  18:30:49  samir\r
38  * Changed property of RBCheckMediaChange which would\r
39  * not disable RBA if media had changed.  GetNumberOfTracks\r
40  * returns num. of tracks or if media changed, re-registers\r
41  * CD and then returns number of tracks.  If media has changed\r
42  * RBAPlayTrack will return an error.\r
43  * \r
44  * Revision 1.9  1995/08/01  19:30:11  samir\r
45  * Added ability to get number of tracks on CD via call.\r
46  * \r
47  * Revision 1.8  1995/07/20  16:13:56  samir\r
48  * Doesn't quit if CD isn't Redbook.\r
49  * \r
50  * Revision 1.7  1995/05/10  11:37:51  samir\r
51  * Checks whether CD-ROM in drive at start of game\r
52  * \r
53  * Revision 1.6  1995/05/09  18:00:08  samir\r
54  * Error cleaned.\r
55  * \r
56  * Revision 1.5  1995/05/09  17:57:43  samir\r
57  * No CD in Drive, then diable RBA\r
58  * \r
59  * Revision 1.4  1995/05/09  17:12:24  samir\r
60  * Added user detection of Redbook Audio.\r
61  * \r
62  * Revision 1.3  1995/05/09  12:04:57  samir\r
63  * Added ability to known when a CD is playing\r
64  * and when it's stopped.\r
65  * \r
66  * Revision 1.2  1995/05/08  11:33:37  samir\r
67  * Initial revision\r
68  * \r
69  * \r
70  */\r
71 \r
72 char rbaudio_rcsid[] = "$Id: rbaudio.new,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";\r
73 \r
74 \r
75 #include <dos.h>\r
76 #include <dpmi.h>\r
77 #include <string.h>\r
78 \r
79 #include "mono.h"\r
80 #include "error.h"\r
81 #include "rbaudio.h"\r
82 #include "fix.h"\r
83 #include "timer.h"\r
84 \r
85 \r
86 #define HSG_CD_PLAYBACK 0\r
87 #define MSF_CD_PLAYBACK 1\r
88 \r
89 #define RBERR_WRITEPROTVIOL     0\r
90 #define RBERR_UNKNOWNUNIT               1\r
91 #define RBERR_DRIVENOTREADY     2\r
92 #define RBERR_UNKNOWNCOMMAND    3\r
93 #define RBERR_CRCERROR                  4\r
94 #define RBERR_BADDRIVEREQ               5\r
95 #define RBERR_SEEKERROR                 6\r
96 #define RBERR_UNKNOWNMEDIA              7\r
97 #define RBERR_SECTORNOTFOUND    8\r
98 #define RBERR_WRITEFAULT                10\r
99 #define RBERR_READFAULT                 12\r
100 #define RBERR_GENERALFAILURE    13\r
101 #define RBERR_BADDISKCHANGE     15\r
102 \r
103 #define RBSTAT_ERROR                            0x8000\r
104 #define RBSTAT_BUSY                             0x0200\r
105 #define RBSTAT_DONE                             0x0100\r
106 \r
107 #pragma pack(1)\r
108 \r
109 \r
110 // Request Header       -----------------------------------------------------\r
111 \r
112 typedef struct _REQHDR {\r
113         unsigned char length;\r
114         unsigned char subunit;\r
115         unsigned char func;\r
116         unsigned short status;\r
117         char array[8];\r
118 } REQHDR;\r
119 \r
120 typedef struct _IOCTL {\r
121         char bpb;\r
122         unsigned short buffer_realoff;\r
123         unsigned short buffer_realseg;\r
124         unsigned short xferlen;\r
125         unsigned short sector;\r
126         unsigned long id;\r
127 } IOCTL;\r
128 \r
129 \r
130 //      CD Information -----------------------------------------------------\r
131 \r
132 static struct {\r
133         char code;                       // Control Block Code\r
134         char track;                      // Track Number\r
135         long start;                      // Start of Track in MSF (Redbook)\r
136         unsigned char info;              // Track Control Info\r
137 } CDTrackInfo = {11,2,0L,0};\r
138 \r
139 static struct {\r
140         REQHDR reqheader;\r
141         IOCTL ioctl;\r
142 } TrackInfoREQ = {{13,0,3,0,""}, {0,0,0,0,0}};\r
143   \r
144 static struct {\r
145         unsigned char code;\r
146         unsigned long devstat;\r
147 } DevStat = {6,0};\r
148 \r
149 static struct {\r
150         REQHDR  reqhdr;\r
151         IOCTL   ioctl;\r
152 } DevStatREQ = {{13,0,3,0,""}, {0,0,0,0,0}};\r
153 \r
154 static struct {\r
155         unsigned char code;\r
156         char byte;\r
157 } MedChg        = {9,0};\r
158 \r
159 static struct {\r
160         REQHDR  reqhdr;\r
161         IOCTL   ioctl;\r
162 } MedChgREQ = {{13,0,3,0,""}, {0,0,0,0,0}};\r
163 \r
164 static struct {\r
165         REQHDR  reqhdr;\r
166 } StopREQ = {{13,0,133,0,""}};\r
167 \r
168 static struct {\r
169         REQHDR  reqhdr;\r
170 } ResumeREQ = {{13,0,136,0,""}};\r
171 \r
172 static struct {\r
173         unsigned char code;\r
174         unsigned char first;\r
175         unsigned char last;\r
176         unsigned long lead_out;\r
177 } CDInfo = {10,0,0,0L};\r
178 \r
179 static struct {\r
180         REQHDR  reqhdr;\r
181         IOCTL   ioctl;\r
182 } CDInfoREQ = {{13,0,3,0,""},{0,0,0,0,0}};\r
183 \r
184 static struct {\r
185         REQHDR  reqheader;\r
186         char    mode;                                   // Play in HSG or MSF(RedBook)\r
187         unsigned long playbeg;\r
188         unsigned long playlen;                // HSG Format\r
189         char            empty;                                          // Empty byte used so that all requests have same size\r
190 } PlayREQ = {{13,0,132,0,""},0,0,0,0};\r
191 \r
192 static struct {\r
193         unsigned char code;\r
194         unsigned char out0in;\r
195         unsigned char out0vol;\r
196         unsigned char out1in;\r
197         unsigned char out1vol;\r
198         unsigned char out2in;\r
199         unsigned char out2vol;\r
200         unsigned char out3in;\r
201         unsigned char out3vol;\r
202 } AUDChannelCtl = {3,0,0,0,0,0,0,0,0};\r
203 \r
204 static struct {\r
205         REQHDR  reqhdr;\r
206         IOCTL           ioctl;\r
207 } AUDChannelCtlREQ = {{13,0,12,0,""},{0,0,0,0,0}};\r
208 \r
209 static struct {\r
210         unsigned char code;\r
211         unsigned char out0in;\r
212         unsigned char out0vol;\r
213         unsigned char out1in;\r
214         unsigned char out1vol;\r
215         unsigned char out2in;\r
216         unsigned char out2vol;\r
217         unsigned char out3in;\r
218         unsigned char out3vol;\r
219 } AUDChannelInfo = {4,0,0,0,0,0,0,0,0};\r
220 \r
221 static struct {\r
222         REQHDR  reqhdr;\r
223         IOCTL           ioctl;\r
224 } AUDChannelInfoREQ = {{13,0,3,0,""},{0,0,0,0,0}};\r
225 \r
226 static struct {\r
227         unsigned char code;\r
228         unsigned char mode;\r
229         unsigned long headloc;\r
230 } HeadInfo = {1,MSF_CD_PLAYBACK,0L};\r
231 \r
232 static struct {\r
233         REQHDR  reqhdr;\r
234         IOCTL           ioctl;\r
235 } HeadInfoREQ = {{13,0,3,0,""},{0,0,0,0,0}};\r
236 \r
237 //@@static struct {\r
238 //@@    ubyte code;\r
239 //@@    ubyte adr;\r
240 //@@    ubyte   tno;\r
241 //@@    ubyte   point;\r
242 //@@    ubyte   min;\r
243 //@@    ubyte   sec;\r
244 //@@    ubyte   frame;\r
245 //@@    ubyte   zero;\r
246 //@@    ubyte   pmin;\r
247 //@@    ubyte   psec;\r
248 //@@    ubyte   pframe;\r
249 //@@} QChannelInfo = {12, MSF_CD_PLAYBACK, 2,0,0,0,0,0,0,0,0    };\r
250 //@@\r
251 //@@static struct {\r
252 //@@    REQHDR  reqhdr;\r
253 //@@    IOCTL           ioctl;\r
254 //@@} QChannelInfoREQ = {{13, 0, 3, 0, ""}, {0,0,0,0,0}};\r
255 \r
256 \r
257 //      Translation from RealMode->Protected mode buffer\r
258 \r
259 typedef struct _REQ_xlatbuf {                   // Buffer for Real Mode Callback\r
260         REQHDR reqheader;\r
261         char ioctl[10];\r
262 } REQ_xlatbuf;\r
263 \r
264 \r
265 \r
266 //      Other Data ---------------------------------------------------------\r
267 \r
268 static unsigned char CDDriveLetter;\r
269 static unsigned long CDNumTracks,CDTrackStart[101];\r
270 static int RedBookEnabled = 0;\r
271 static int RedBookPlaybackType = MSF_CD_PLAYBACK;\r
272 static fix Playback_Start_Time = 0;\r
273 static fix Playback_Pause_Time = 0;\r
274 static fix Playback_Length = 0;\r
275                                                          \r
276 \r
277 //      Prototypes ---------------------------------------------------------\r
278 \r
279 int RBSendRequest(char *request, char *xferptr, int xferlen);   \r
280 unsigned long msf_to_lsn(unsigned long msf);\r
281 unsigned long lsn_to_msf(unsigned long lsn);\r
282 \r
283 \r
284 //      --------------------------------------------------------------------\r
285 \r
286 void RBAInit(ubyte cd_drive_num)        //drive a == 0, drive b == 1\r
287 {\r
288         union REGS regs;\r
289 \r
290 //      Detect presence of CD-ROM\r
291         regs.x.eax = 0x1500;\r
292         regs.x.ebx = 0;\r
293         int386(0x2f, &regs, &regs);\r
294         \r
295         if (regs.x.ebx == 0) \r
296                 RBADisable();                                           // Disable RedBook\r
297         //      Error("RBA Error: MSCDEX.EXE compatible driver couldn't be found.");\r
298         else {\r
299                 CDDriveLetter = cd_drive_num;\r
300 //              CDDriveLetter = (unsigned char)regs.x.ecx;\r
301 \r
302                 RBAEnable();\r
303                 RBACheckMediaChange();\r
304 \r
305                 RBSendRequest((char*)&DevStatREQ, (char*)&DevStat, sizeof(DevStat));\r
306                 \r
307         // If Door drive open, or no disc in CD-ROM, then Redbook is Disabled.\r
308                 if ((DevStat.devstat&2048) || (DevStat.devstat&1) || RBAEnabled() == 0) \r
309                         RBADisable();\r
310 \r
311 //@@            if (DevStat.devstat&4) \r
312 //@@                    mprintf((0, "supports cooked and raw reading.\n"));\r
313 //@@            else \r
314 //@@                    mprintf((0, "supports only cooked reading.\n"));\r
315 //@@\r
316 //@@            if (DevStat.devstat&256) \r
317 //@@                    mprintf((0, "audio channel manipulation.\n"));\r
318 //@@            else \r
319 //@@                    mprintf((0, "no audio channel manipulation.\n"));\r
320         \r
321                 if (DevStat.devstat&512) {\r
322 //                      RedBookPlaybackType = MSF_CD_PLAYBACK;\r
323                         mprintf((0, "supports HSG and RedBook addressing mode.\n"));\r
324                 }\r
325                 else {\r
326 //                      RedBookPlaybackType = HSG_CD_PLAYBACK;\r
327                         mprintf((0, "supports HSG addressing only.\n"));\r
328                 }\r
329                         \r
330                 RedBookPlaybackType = MSF_CD_PLAYBACK;\r
331 \r
332         }\r
333 }\r
334 \r
335 //find out how many tracks on the CD, and their starting locations\r
336 void RBARegisterCD(void)\r
337 {\r
338         int i;\r
339         int error;\r
340 \r
341         //      Get CD Information First\r
342         RBACheckMediaChange();\r
343 \r
344         error = RBSendRequest((char*)&CDInfoREQ, (char*)&CDInfo, sizeof(CDInfo));\r
345 \r
346         if (error & RBSTAT_ERROR) {             //error!\r
347                 CDNumTracks = 0;\r
348                 return;\r
349         }\r
350         \r
351         CDNumTracks = (CDInfo.last-CDInfo.first)+1;\r
352 \r
353         // Define Track Starts\r
354         for (i=CDInfo.first; i<=CDNumTracks; i++)\r
355         {\r
356                 CDTrackInfo.track = i;\r
357                 RBSendRequest((char *)&TrackInfoREQ, (char*)&CDTrackInfo, sizeof(CDTrackInfo));\r
358                 CDTrackStart[i] = CDTrackInfo.start;\r
359         }\r
360 \r
361         CDTrackStart[i] = CDInfo.lead_out;\r
362\r
363 \r
364 \r
365 long RBAGetDeviceStatus()\r
366 {\r
367         RBSendRequest((char*)&DevStatREQ, (char*)&DevStat, sizeof(DevStat));\r
368         return (long)DevStat.devstat;\r
369 }\r
370 \r
371 \r
372 int RBAGetNumberOfTracks(void)\r
373 {\r
374         //      Get CD Information\r
375         if (RBACheckMediaChange())\r
376                 RBARegisterCD(); \r
377 \r
378         return CDNumTracks;\r
379 }\r
380 \r
381 \r
382 int RBAPlayTrack(int track)\r
383 {\r
384         unsigned long playlen;\r
385         int min, sec;\r
386 \r
387         Playback_Start_Time = 0;\r
388         Playback_Length = 0;\r
389 \r
390         if (track < CDInfo.first || track > CDInfo.last) {\r
391                 mprintf((0,"CD not Redbook Compatible. Will not play track.\n"));\r
392         }\r
393 //              Error("RBA Error: Track %d doesn't exist on CD!!!", track);\r
394         \r
395         if (RBACheckMediaChange()) {\r
396                 mprintf((0, "Unable to play track due to CD change.\n"));\r
397                 return 0;\r
398         }\r
399 \r
400         //      Play the track now!!!\r
401         PlayREQ.mode = RedBookPlaybackType;\r
402         PlayREQ.playbeg = CDTrackStart[track];\r
403 \r
404         if (RedBookPlaybackType == MSF_CD_PLAYBACK) {\r
405                 PlayREQ.playlen = \r
406                         msf_to_lsn(CDTrackStart[track+1]) - msf_to_lsn(CDTrackStart[track]);\r
407         }\r
408         else {\r
409                 mprintf((1, "RBERR: No! No! No! This shouldn't happen (HSG_CD_PLAYBACK).\n"));\r
410                 Int3();\r
411                 PlayREQ.playlen = CDTrackStart[track+1] - CDTrackStart[track];\r
412         }\r
413         RBSendRequest((char *)&PlayREQ,NULL,0);\r
414 \r
415         playlen = msf_to_lsn(CDTrackStart[track+1]) - msf_to_lsn(CDTrackStart[track]);\r
416         playlen = lsn_to_msf(playlen);\r
417         min   = (int)((playlen >> 16) & 0xFF);\r
418         sec   = (int)((playlen >>  8) & 0xFF);\r
419 \r
420         Playback_Start_Time = timer_get_fixed_seconds();\r
421         Playback_Length = i2f(min*60+sec);\r
422 \r
423         mprintf( (0,"Playing Track %d (len: %d secs)\n", track, min*60+sec) );\r
424 \r
425         return 1;\r
426 }\r
427 \r
428 //plays tracks first through last, inclusive\r
429 int RBAPlayTracks(int first, int last)\r
430 {\r
431         unsigned long playlen;\r
432         int min, sec;\r
433 \r
434         Playback_Start_Time = 0;\r
435         Playback_Length = 0;\r
436 \r
437         if (first < CDInfo.first || last > CDInfo.last) {\r
438                 mprintf((0,"Invalid start or end track.\n"));\r
439         }\r
440 //              Error("RBA Error: Track %d doesn't exist on CD!!!", track);\r
441         \r
442         if (RBACheckMediaChange()) {\r
443                 mprintf((0, "Unable to play track due to CD change.\n"));\r
444                 return 0;\r
445         }\r
446 \r
447         //      Play the track now!!!\r
448         PlayREQ.mode = RedBookPlaybackType;\r
449         PlayREQ.playbeg = CDTrackStart[first];\r
450 \r
451         if (RedBookPlaybackType == MSF_CD_PLAYBACK) {\r
452                 PlayREQ.playlen = \r
453                         msf_to_lsn(CDTrackStart[last+1]) - msf_to_lsn(CDTrackStart[first]);\r
454         }\r
455         else {\r
456                 mprintf((1, "RBERR: No! No! No! This shouldn't happen (HSG_CD_PLAYBACK).\n"));\r
457                 Int3();\r
458                 PlayREQ.playlen = CDTrackStart[last+1] - CDTrackStart[first];\r
459         }\r
460         RBSendRequest((char *)&PlayREQ,NULL,0);\r
461 \r
462         playlen = msf_to_lsn(CDTrackStart[last+1]) - msf_to_lsn(CDTrackStart[first]);\r
463         playlen = lsn_to_msf(playlen);\r
464         min   = (int)((playlen >> 16) & 0xFF);\r
465         sec   = (int)((playlen >>  8) & 0xFF);\r
466 \r
467         Playback_Start_Time = timer_get_fixed_seconds();\r
468         Playback_Length = i2f(min*60+sec);\r
469 \r
470         mprintf( (0,"Playing Tracks %d-%d (len: %d secs)\n", first,last,min*60+sec) );\r
471 \r
472         return 1;\r
473 }\r
474 \r
475 \r
476 void RBAPause()\r
477 {\r
478         RBSendRequest((char *)&StopREQ, NULL, 0);\r
479         Playback_Pause_Time = timer_get_fixed_seconds();\r
480 }\r
481 \r
482 \r
483 int RBAResume()\r
484 {\r
485         if (RBACheckMediaChange()) {\r
486                 RBARegisterCD();\r
487                 return RBA_MEDIA_CHANGED;\r
488         }\r
489         RBSendRequest((char *)&ResumeREQ, NULL, 0);\r
490 \r
491         Playback_Start_Time += timer_get_fixed_seconds() - Playback_Pause_Time;\r
492 \r
493         return 1;\r
494 }\r
495 \r
496 \r
497 void RBAStop()\r
498 {\r
499         if (RBACheckMediaChange())\r
500                 RBARegisterCD();\r
501 \r
502         RBSendRequest((char *)&StopREQ,NULL,0);      \r
503 }\r
504 \r
505 \r
506 void RBASetStereoAudio(RBACHANNELCTL *channels)\r
507 {\r
508         AUDChannelCtl.out0in = channels->out0in;\r
509         AUDChannelCtl.out0vol = channels->out0vol;\r
510         AUDChannelCtl.out1in = channels->out1in;\r
511         AUDChannelCtl.out1vol = channels->out1vol;\r
512         AUDChannelCtl.out2in = AUDChannelCtl.out2vol = 0;\r
513         AUDChannelCtl.out3in = AUDChannelCtl.out3vol = 0;\r
514         \r
515         RBSendRequest((char*)&AUDChannelCtlREQ, (char*)&AUDChannelCtl, sizeof(AUDChannelCtl));\r
516 }\r
517 \r
518 \r
519 void RBASetQuadAudio(RBACHANNELCTL *channels)\r
520 {\r
521         AUDChannelCtl.out0in = (unsigned char)channels->out0in;\r
522         AUDChannelCtl.out0vol = (unsigned char)channels->out0vol;\r
523         AUDChannelCtl.out1in = (unsigned char)channels->out1in;\r
524         AUDChannelCtl.out1vol = (unsigned char)channels->out1vol;\r
525         AUDChannelCtl.out2in = (unsigned char)channels->out2in;\r
526         AUDChannelCtl.out2vol = (unsigned char)channels->out2vol;\r
527         AUDChannelCtl.out3in = (unsigned char)channels->out3in;\r
528         AUDChannelCtl.out3vol = (unsigned char)channels->out3vol;\r
529         \r
530         RBSendRequest((char*)&AUDChannelCtlREQ, (char*)&AUDChannelCtl, sizeof(AUDChannelCtl));\r
531 }\r
532 \r
533 \r
534 void RBAGetAudioInfo(RBACHANNELCTL *channels)\r
535 {\r
536         RBSendRequest((char*)&AUDChannelInfoREQ, (char*)&AUDChannelInfo, sizeof(AUDChannelInfo));\r
537         \r
538         channels->out0in = (int)AUDChannelInfo.out0in;\r
539         channels->out0vol = (int)AUDChannelInfo.out0vol;\r
540         channels->out1in = (int)AUDChannelInfo.out1in;\r
541         channels->out1vol = (int)AUDChannelInfo.out1vol;\r
542         channels->out2in = (int)AUDChannelInfo.out2in;\r
543         channels->out2vol = (int)AUDChannelInfo.out2vol;\r
544         channels->out3in = (int)AUDChannelInfo.out3in;\r
545         channels->out3vol = (int)AUDChannelInfo.out3vol;\r
546 \r
547 }\r
548 \r
549 \r
550 void RBASetChannelVolume(int channel, int volume) \r
551 {\r
552         //RBACHANNELCTL channels;\r
553         \r
554         RBSendRequest((char*)&AUDChannelInfoREQ, (char*)&AUDChannelInfo, sizeof(AUDChannelInfo));\r
555 \r
556         AUDChannelCtl.out0in = AUDChannelInfo.out0in;\r
557         AUDChannelCtl.out0vol = AUDChannelInfo.out0vol;\r
558         AUDChannelCtl.out1in = AUDChannelInfo.out1in;\r
559         AUDChannelCtl.out1vol = AUDChannelInfo.out1vol;\r
560         AUDChannelCtl.out2in = AUDChannelInfo.out2in;\r
561         AUDChannelCtl.out2vol = AUDChannelInfo.out2vol;\r
562         AUDChannelCtl.out3in = AUDChannelInfo.out3in;\r
563         AUDChannelCtl.out3vol = AUDChannelInfo.out3vol;\r
564 \r
565         if (channel == 0) AUDChannelCtl.out0vol = (unsigned char)volume;\r
566         if (channel == 1) AUDChannelCtl.out1vol = (unsigned char)volume;\r
567         if (channel == 2) AUDChannelCtl.out2vol = (unsigned char)volume;\r
568         if (channel == 3) AUDChannelCtl.out3vol = (unsigned char)volume;\r
569         \r
570         RBSendRequest((char*)&AUDChannelCtlREQ,(char*)&AUDChannelCtl, sizeof(AUDChannelCtl));\r
571 \r
572 }\r
573 \r
574 \r
575 void RBASetVolume(int volume)\r
576 {\r
577         RBASetChannelVolume(0,volume);\r
578         RBASetChannelVolume(1,volume);\r
579 }\r
580 \r
581 \r
582 long RBAGetHeadLoc(int *min, int *sec, int *frame)\r
583 {\r
584         unsigned long loc;\r
585 \r
586         if (RBACheckMediaChange())\r
587                 return RBA_MEDIA_CHANGED;\r
588 \r
589         HeadInfo.mode = RedBookPlaybackType;\r
590         RBSendRequest((char*)&HeadInfoREQ, (char*)&HeadInfo, sizeof(HeadInfo));\r
591         \r
592         if (RedBookPlaybackType == MSF_CD_PLAYBACK)\r
593                 loc = HeadInfo.headloc;\r
594         else \r
595                 loc = lsn_to_msf(HeadInfo.headloc);\r
596 \r
597         *min   = (int)((loc >> 16) & 0xFF);\r
598         *sec   = (int)((loc >>  8) & 0xFF);\r
599         *frame = (int)((loc >>  0) & 0xFF);\r
600 \r
601         return loc;\r
602 }               \r
603 \r
604 \r
605 int RBAPeekPlayStatus()\r
606 {\r
607         if ((timer_get_fixed_seconds()-Playback_Start_Time) > Playback_Length) return 0;\r
608         else return 1; \r
609 }\r
610         \r
611 \r
612 int RBAEnabled()\r
613 {\r
614         if (RedBookEnabled < 1) return 0;\r
615         else return 1;\r
616 }\r
617 \r
618 \r
619 void RBAEnable()\r
620 {\r
621         RedBookEnabled = 1;\r
622         mprintf((0, "Enabling Redbook...\n"));\r
623 }\r
624 \r
625 \r
626 void RBADisable()\r
627 {\r
628         RedBookEnabled = 0;\r
629         mprintf((0, "Disabling Redbook...\n"));\r
630 }\r
631 \r
632 \r
633 \r
634 //      RB functions:  Internal to RBA library  -----------------------------\r
635 \r
636 //returns 1 if media has changed, else 0\r
637 int RBACheckMediaChange()\r
638 {\r
639         RBSendRequest((char *)&MedChgREQ, (char*)&MedChg, sizeof(MedChg));\r
640 \r
641         if (MedChg.byte == 255 || MedChg.byte == 0) {\r
642                 // New media in drive (or maybe no media in drive)\r
643                 mprintf((0,"CD-ROM Media change detected\n"));\r
644                 return 1;\r
645         }\r
646         return 0;\r
647 }\r
648 \r
649 \r
650 //      Send Request\r
651 \r
652 //returns 16-bit value.  Bit 15 means error.\r
653 //WE NEED SYMBOLOIC CONSTANTS FOR ALL RETURN CODES & STATUS BITS\r
654 int RBSendRequest(char *request, char *xferptr, int xferlen)\r
655 {\r
656         //union REGS regs;\r
657         dpmi_real_regs rregs;\r
658 \r
659         IOCTL *ioctl;\r
660         REQ_xlatbuf *xlat_req;                          // Translated Buffer Request \r
661         char *xlat_xferptr;                                     // Translated Buffer Transfer Buffer Ptr\r
662         \r
663         unsigned short status;\r
664         \r
665         if (!RedBookEnabled) return 0;  // Don't send request if no RBA\r
666 \r
667         memset(&rregs,0,sizeof(dpmi_real_regs));\r
668 \r
669 // Get Temporary Real Mode Buffer for request translation\r
670         xlat_req = (REQ_xlatbuf *)dpmi_get_temp_low_buffer(128+xferlen);\r
671         memcpy(xlat_req, request, sizeof(REQHDR)+sizeof(IOCTL));\r
672         ioctl = (IOCTL *)(((char*)xlat_req)+sizeof(REQHDR));\r
673 \r
674 //      Set Transfer Buffer in IOCTL reqion of 'request'        \r
675         if (xferlen && xferptr) {\r
676                 xlat_xferptr = ((char*)xlat_req) + 128;\r
677                 memcpy(xlat_xferptr, xferptr, xferlen);\r
678                 \r
679                 ioctl->buffer_realoff = DPMI_real_offset(xlat_xferptr);\r
680                 ioctl->buffer_realseg = DPMI_real_segment(xlat_xferptr);\r
681                 ioctl->xferlen = xferlen;\r
682         }\r
683 \r
684 //      Setup and Send Request Packet\r
685         rregs.eax = 0x1510;\r
686         rregs.ecx = (unsigned)(CDDriveLetter);\r
687         rregs.es  = DPMI_real_segment(xlat_req);\r
688         rregs.ebx = DPMI_real_offset(xlat_req);\r
689         dpmi_real_int386x(0x2f, &rregs);\r
690 \r
691 //      Return Translate Buffer to Protected mode 'xferptr'\r
692         if (xferlen && xferptr) {\r
693                 memcpy(xferptr, xlat_xferptr, xferlen);\r
694         }\r
695         memcpy(request, xlat_req, sizeof(REQHDR)+sizeof(IOCTL));\r
696         \r
697 //      Check for Errors.\r
698         status = ((REQHDR *)request)->status;\r
699 \r
700         if (status & RBSTAT_ERROR) {\r
701                 mprintf((0,"Error in SendRequest: %x.\n", status));\r
702         }\r
703 \r
704         return status;\r
705\r
706                 \r
707 \r
708 //      Converts Logical Sector Number to Minutes Seconds Frame Format\r
709 \r
710 unsigned long lsn_to_msf(unsigned long lsn)\r
711 {\r
712    unsigned long min,sec,frame;\r
713    lsn += 150;\r
714 \r
715         min   =  lsn / (60*75);\r
716    lsn   =  lsn % (60*75);\r
717         sec   =  lsn / 75;\r
718    lsn   =  lsn % 75;\r
719         frame =  lsn;\r
720 \r
721         return((min << 16) + (sec << 8) + (frame << 0));\r
722 }\r
723 \r
724 // convert minutes seconds frame format to a logical sector number.\r
725 \r
726 unsigned long msf_to_lsn(unsigned long msf)\r
727 {\r
728         unsigned long min,sec,frame;\r
729 \r
730         min   = (msf >> 16) & 0xFF;\r
731    sec   = (msf >>  8) & 0xFF;\r
732    frame = (msf >>  0) & 0xFF;\r
733 \r
734         return(  (min * 60*75) + (sec * 75) + frame - 150  );\r
735 }\r
736 \r