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