1 #include "osd_cd.h"
2
3 /*
4 * Mscdex part
5 */
6
7 // Il s'agit d'une bidouille infame pour que DJGPP n'aligne pas les membres
8 // unsigned short des structures sur des offsets pairs. (Ce qui bien sur fait
9 // tout foirer et que j'ai mis deux jours a decouvrir!!)
10 #define DW(id) (*((unsigned short *)(&id)))
11 #define DD(id) (*((unsigned int *)(&id)))
12
13 #undef BYTE
14 #undef WORD
15 #undef DWORD
16
17 typedef unsigned char BYTE;
18 typedef struct {
19 BYTE b1;
20 BYTE b2;
21 } WORD;
22
23 typedef struct {
24 BYTE b1;
25 BYTE b2;
26 BYTE b3;
27 BYTE b4;
28 } DWORD;
29
30
31 //-- Structures --------------------------------------------------------------
32 typedef struct {
33 BYTE len1;
34 BYTE unit;
35 BYTE command;
36 WORD status;
37 BYTE reserved[8];
38 BYTE descriptor;
39 WORD adr_off;
40 WORD adr_seg;
41 WORD len2;
42 WORD secnum;
43 WORD ptr_off;
44 WORD ptr_seg;
45 } IOCTLI;
46
47 typedef struct {
48 BYTE control;
49 BYTE lowest;
50 BYTE highest;
51 DWORD total;
52 } DISKINFO;
53
54 typedef struct {
55 BYTE control;
56 BYTE track;
57 DWORD loc;
58 BYTE info;
59 } TRACKINFO;
60
61 typedef struct {
62 BYTE len;
63 BYTE unit;
64 BYTE command;
65 WORD status;
66 BYTE reserved[8];
67 BYTE mode;
68 DWORD loc;
69 DWORD secnum;
70 } PLAYREQ;
71
72 typedef struct {
73 BYTE len;
74 BYTE unit;
75 BYTE command;
76 WORD status;
77 BYTE reserved[8];
78 BYTE mode_addr;
79 WORD ptr_off;
80 WORD ptr_seg;
81 WORD nb_to_read;
82 DWORD secnum;
83 BYTE mode_lect;
84 BYTE interleave_size;
85 BYTE interleave_skip;
86 } READREQ;
87
88 typedef struct {
89 BYTE len;
90 BYTE unit;
91 BYTE command;
92 WORD status;
93 BYTE reserved[8];
94 } STOPREQ;
95
96 typedef struct {
97 BYTE control;
98 BYTE mode;
99 DWORD loc;
100 } HEADINFO;
101
102 //-- Imported Variables ------------------------------------------------------
103 char global_error[80];
104
105 //-- Private Variables -------------------------------------------------------
106 static __dpmi_regs _regs;
107 static int cdda_track_start;
108 static int cdda_track_end;
109 static int cdda_loop_counter;
110
111 //-- Public Variables --------------------------------------------------------
112 int cdda_min_track;
113 int cdda_max_track;
114 int cdda_first_drive;
115 int cdda_nb_of_drives;
116 int cdda_current_drive;
117 int cdda_current_track;
118 int cdda_playing;
119 int cdda_disk_length;
120
121 void osd_cd_play_audio_track_mscdex(UChar track);
122 int osd_cd_init_mscdex(char* device_name);
123 void osd_cd_length_mscdex(int* min,
124 int* sec,
125 int* fra);
126 void osd_cd_stop_audio_mscdex(void);
127 void osd_cd_play_audio_range_mscdex(int min_from,
128 int sec_from,
129 int fra_from,
130 int min_to,
131 int sec_to,
132 int fra_to);
133 void osd_cd_track_info_mscdex(UChar track,
134 int* min,
135 int* sec,
136 int* fra,
137 int* control);
138 void osd_cd_read_mscdex(unsigned char* p,unsigned long nb_sect);
139 void osd_cd_nb_tracks_mscdex(int* first,
140 int* last);
141 void osd_cd_close_mscdex(void);
142
143 /*
144 * Aspi part
145 */
146
147 static int TB;
148 static int DB;
149 #define DOSS _go32_info_block.selector_for_linear_memory
150 #define INT r.x.sp = r.x.ss = r.x.flags = 0, _go32_dpmi_simulate_int
151 #define __dpmi_regs _go32_dpmi_registers
152 #define GTB (_go32_info_block.linear_address_of_transfer_buffer & 0xfffff)
153
154 union {
155 SRB_HAInquiry hai;
156 SRB_GDEVBlock gdb;
157 SRB_ExecSCSICmd srb;
158 SRB_Abort ab;
159 SRB_BusDeviceReset res;
160 } SRB_Everything;
161
162 static aspi_fd = -1;
163 static int aspi_entry_seg;
164 static int aspi_entry_ofs;
165 static _go32_dpmi_seginfo dos_buf;
166
167 long aspi_buffer_length = 128 * 1024;
168 char aspi_sense[SENSE_LEN];
169
170 static int dat, aspi_stat;
171 static unsigned char cdb[10];
172 static unsigned long block_size = 20 * 512;
173
174
175 static void
aspi_entry(void * srb,int srblen)176 aspi_entry(void *srb, int srblen)
177 {
178 __dpmi_regs r;
179 int i;
180 int sp = GTB + 4090;
181 /* printf("%x = %x + 4090\n", sp, GTB);*/
182 dosmemput(srb, srblen, TB);
183 /* printf("go32's TB at 0x%x 0x%x\n", _go32_info_block.linear_address_of_transfer_buffer, GTB); */
184 /* printf("entry: SRB at 0x%lx (dos TB at 0x%x)\n", srb, TB); */
185 memset(&r, 0, sizeof(r));
186 r.x.cs = aspi_entry_seg;
187 r.x.ip = aspi_entry_ofs;
188 sp -= 2; _farpokew(DOSS, sp, TB >> 4);
189 sp -= 2; _farpokew(DOSS, sp, TB & 15);
190 r.x.ss = GTB >> 4;
191 r.x.sp = (sp - r.x.ss*16);
192 /* printf("entry: go %04x:%04x, stack %04x:%04x (now 0x%x)\n",
193 r.x.cs, r.x.ip, r.x.ss, r.x.sp, sp); */
194 #if 0
195 printf("stack[0x%x]: ", r.x.ss * 16 + r.x.sp);
196 for (i=0; i<37; i++)
197 printf(" %02x", _farpeekb(DOSS, r.x.ss * 16 + r.x.sp + i));
198 printf("\n");
199 #endif
200 _go32_dpmi_simulate_fcall(&r);
201 while (_farpeekb(DOSS, TB+1) == 0);
202 dosmemget(TB, srblen, srb);
203 }
204
205 int
aspi_init(void)206 aspi_init(void)
207 {
208 __dpmi_regs r;
209 SRB_HAInquiry hai;
210
211 setbuf(stdout, 0);
212 dos_buf.size = (aspi_buffer_length/16) + (sizeof(SRB_Everything)+15) / 16;
213 if (_go32_dpmi_allocate_dos_memory(&dos_buf))
214 {
215 /*
216 * fprintf(stderr, "ASPI Error: Not able to allocate %d Kb buffer\n", aspi_buffer_length / 1024);
217 */
218 aspi_fd = -1;
219 return -1;
220 }
221 TB = dos_buf.rm_segment * 16;
222 DB = TB + (sizeof(SRB_Everything) + 15) & ~15;
223
224 aspi_fd = open("SCSIMGR$", O_RDONLY);
225 if (aspi_fd < 0)
226 {
227 perror("SCSIMGR$");
228 aspi_fd = -1;
229 return -1;
230 }
231
232 r.x.ax = 0x4402;
233 r.x.bx = aspi_fd;
234 r.x.cx = 4;
235 r.x.ds = TB >> 4;
236 r.x.dx = TB & 15;
237 INT(0x21, &r);
238 aspi_entry_ofs = _farpeekw(DOSS, TB);
239 aspi_entry_seg = _farpeekw(DOSS, TB+2);
240 close(aspi_fd);
241 aspi_fd = 0;
242
243 memset(&hai, 0, sizeof(hai));
244 hai.SRB_Cmd = SC_HA_INQUIRY;
245 aspi_entry(&hai, sizeof(hai));
246
247 return hai.HA_Count;
248 }
249
250 int
aspi_close(void)251 aspi_close(void)
252 {
253 if (aspi_fd)
254 return;
255 _go32_dpmi_free_dos_memory(&dos_buf);
256 aspi_fd = -1;
257 return 0;
258 }
259
260 int
aspi_device_type(int aspi_id)261 aspi_device_type(int aspi_id)
262 {
263 SRB_GDEVBlock gd;
264 if (aspi_fd)
265 return;
266 memset(&gd, 0, sizeof(gd));
267 gd.SRB_Cmd = SC_GET_DEV_TYPE;
268 gd.SRB_HaId = ASPI_ID2HOSTAD(aspi_id);
269 gd.SRB_Target = ASPI_ID2TARGET(aspi_id);
270 gd.SRB_Lun = ASPI_ID2LUN(aspi_id);
271 aspi_entry(&gd, sizeof(gd));
272 return (gd.SRB_Status == SS_COMP) ? gd.SRB_DeviceType : -1;
273 }
274
275 int
aspi_exec(int id,void * buf,int buflen,int rw,char * cdb,int cdblen)276 aspi_exec(int id, void *buf, int buflen, int rw, char *cdb, int cdblen)
277 {
278 char *cptr;
279 SRB_ExecSCSICmd srb;
280
281 if (aspi_fd)
282 return;
283
284 memset(&srb, 0, sizeof(srb));
285 srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
286 srb.SRB_Status = 0;
287 srb.SRB_HaId = ASPI_ID2HOSTAD(id);
288 srb.SRB_Flags = SRB_DIR_SCSI;
289 srb.SRB_Target = ASPI_ID2TARGET(id);
290 srb.SRB_Lun = ASPI_ID2LUN(id);
291 srb.SRB_BufLen = buflen;
292 srb.SRB_SenseLen = SENSE_LEN;
293 srb.SRB_BufPointerOfs = DB & 15;
294 srb.SRB_BufPointerSeg = DB >> 4;
295 srb.SRB_CDBLen = cdblen;
296 memcpy(srb.cptr, cdb, cdblen);
297 if (rw & ASPI_RW_WRITE)
298 dosmemput(buf, buflen, DB);
299 aspi_entry(&srb, sizeof(srb));
300 if (rw & ASPI_RW_READ)
301 dosmemget(DB, buflen, buf);
302 memcpy(aspi_sense, srb.cptr+cdblen, SENSE_LEN);
303 return srb.SRB_Status;
304 }
305
aspi_set_blocksize(unsigned long new_block_size)306 void aspi_set_blocksize(unsigned long new_block_size)
307
308 {
309 unsigned char buffer[12];
310 block_size = new_block_size;
311 memset(cdb, 0, 6);
312 cdb[0] = 0x15;
313 cdb[4] = 0x0c;
314 memset(buffer, 0, sizeof(buffer));
315 buffer[2] = 0x10;
316 buffer[3] = 8;
317 buffer[9] = (block_size) >> 16;
318 buffer[10] = (block_size) >> 8;
319 buffer[11] = (block_size);
320 aspi_stat = aspi_exec(dat, buffer, 12, ASPI_RW_WRITE, cdb, 6);
321 }
322
323
324 int osd_cd_init_aspi(char* device_name);
325 void osd_cd_close_aspi();
326 void osd_cd_nb_tracks_aspi(int* first,
327 int* last);
328 void osd_cd_track_info_aspi(UChar track,
329 int* min,
330 int* sec,
331 int* fra,
332 int* control);
333 void osd_cd_read_aspi(unsigned char *buffer, unsigned long sector);
334 void osd_cd_play_audio_range_aspi(int min_from,
335 int sec_from,
336 int fra_from,
337 int min_to,
338 int sec_to,
339 int fra_to);
340 void osd_cd_play_audio_track_aspi(UChar track);
341 void osd_cd_stop_audio_aspi(void);
342 /*
343 * Generic part
344 */
345
346 osd_cd_driver_type osd_cd_driver = mscdex_driver;
347
348 //----------------------------------------------------------------------------
osd_cd_init(char * device_name)349 int osd_cd_init(char* device_name)
350 {
351 switch (osd_cd_driver)
352 {
353 case mscdex_driver:
354 return osd_cd_init_mscdex(device_name);
355 case aspi_driver:
356 return osd_cd_init_aspi(device_name);
357 default:
358 return 0;
359 }
360 }
361 //----------------------------------------------------------------------------
osd_cd_init_aspi(char * device_name)362 int osd_cd_init_aspi(char* device_name)
363 {
364 int nb_device = atoi(device_name);
365 int nh = aspi_init();
366
367 if (nh == -1)
368 return 1;
369
370 if (!nb_device) /* if asked to use the 0th device, set it to 1 */
371 nb_device = 1;
372
373 for (dat=0; dat<64*nh; dat++)
374 {
375 aspi_stat = aspi_device_type(dat);
376 if (aspi_stat == -1)
377 continue;
378 if (aspi_stat == DTYPE_CROM) /* Check for cdrom drive */
379 {
380 Log("dos/osd_cd.c : detected cdrom device number %d at scsi(%d:%d:%d)\n",
381 nb_device,
382 ASPI_ID2HOSTAD(dat),
383 ASPI_ID2TARGET(dat),
384 ASPI_ID2LUN(dat));
385
386 nb_device --;
387
388 if (!nb_device)
389 {
390 aspi_set_blocksize(2048);
391 return 0;
392 }
393 }
394 }
395
396 return 1;
397 }
398 //----------------------------------------------------------------------------
osd_cd_init_mscdex(char * device_name)399 int osd_cd_init_mscdex(char* device_name)
400 {
401 IOCTLI cmd;
402 DISKINFO di;
403
404 if (strcmp(device_name,""))
405 cdda_current_drive = toupper(device_name[0])-'A';
406 else
407 cdda_current_drive = 0;
408
409 strcpy(global_error, "");
410
411 Log("dos/osd_cd.c : drive number %d (%c) is used for mscdex init\n",
412 cdda_current_drive,
413 'A' + cdda_current_drive);
414
415 cdda_min_track = cdda_max_track = 0;
416 cdda_current_track = 0;
417 cdda_playing = 0;
418 cdda_loop_counter = 0;
419
420 memset(&_regs, 0, sizeof(_regs));
421 _regs.d.eax = 0x1500;
422 _regs.d.ebx = 0;
423
424 if (__dpmi_int(0x2f, &_regs) == 0) {
425
426 Log("dos/osd_cd.c : valid dpmi int called\n");
427
428 cdda_first_drive = _regs.d.ecx;
429 cdda_nb_of_drives = _regs.d.ebx;
430
431 if ((cdda_current_drive<cdda_first_drive)||
432 (cdda_current_drive>(cdda_first_drive+cdda_nb_of_drives))) {
433 if (cdda_current_drive!=-1)
434 strcpy(global_error,
435 "CDAUDIO: WARNING - Invalid drive override!");
436 cdda_current_drive = cdda_first_drive;
437 }
438
439 cmd.len1 = sizeof(IOCTLI);
440 cmd.unit = 0;
441 cmd.command = 3;
442 cmd.descriptor = 0;
443 DW(cmd.adr_seg) = (__tb>>4);
444 DW(cmd.adr_off) = sizeof(IOCTLI);
445 DW(cmd.len2) = 7;
446 DW(cmd.secnum) = 0;
447 DW(cmd.ptr_seg) = 0;
448 DW(cmd.ptr_off) = 0;
449 di.control = 10;
450
451 dosmemput(&cmd, sizeof(IOCTLI), __tb);
452 dosmemput(&di, sizeof(DISKINFO), (__tb + sizeof(IOCTLI)));
453
454 memset(&_regs, 0, sizeof(_regs));
455 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
456 _regs.x.bx = 0;
457 _regs.x.cx = cdda_current_drive;
458 _regs.x.ax = 0x1510;
459 __dpmi_int(0x2f, &_regs);
460
461 dosmemget(__tb, sizeof(IOCTLI), &cmd);
462 dosmemget((__tb + sizeof(IOCTLI)), sizeof(DISKINFO), &di);
463
464 if (DW(cmd.status)&0x8000) {
465 strcpy(global_error, "CDAUDIO - FATAL: No CD in drive!");
466 Log("dos/osd_cd.c : No cd in drive\n");
467 return 1;
468 }
469
470 cdda_min_track = di.lowest;
471 cdda_max_track = di.highest;
472 cdda_disk_length = DD(di.total);
473
474 if (global_error[0]==0)
475 strcpy(global_error, "CDAUDIO: Initialization OK!");
476
477 return 0;
478 }
479 strcpy(global_error,
480 "CDAUDIO: FATAL - No CD-ROM driver was found!");
481 return 1;
482 }
483 //----------------------------------------------------------------------------
osd_cd_play_audio_track(UChar track)484 void osd_cd_play_audio_track(UChar track)
485 {
486 switch (osd_cd_driver)
487 {
488 case mscdex_driver:
489 osd_cd_play_audio_track_mscdex(track);
490 break;
491 case aspi_driver:
492 osd_cd_play_audio_track_aspi(track);
493 break;
494
495 default:
496 }
497 }
498 //----------------------------------------------------------------------------
osd_cd_play_audio_track_aspi(UChar track)499 void osd_cd_play_audio_track_aspi(UChar track)
500 {
501 /*
502 unsigned char *sense;
503 memset(cdb, 0, 10);
504
505 cdb[0] = SCSI_PLAYA_TKIN;
506 cdb[4] = track;
507 cdb[5] = 0;
508 cdb[7] = track + 1;
509 cdb[8] = 0;
510
511 aspi_stat = aspi_exec(dat, NULL, block_size, 0, cdb, 10);
512 */
513 /* This way of doing isn't right, please tell me if you know */
514
515 int m1, s1, f1, m2, s2, f2, dum;
516 osd_cd_track_info_aspi(track,
517 &m1,
518 &s1,
519 &f1,
520 &dum);
521 osd_cd_track_info_aspi(track + 1,
522 &m2,
523 &s2,
524 &f2,
525 &dum);
526
527 osd_cd_play_audio_range_aspi(m1,
528 s1,
529 f1,
530 m2,
531 s2,
532 f2);
533
534 /* We may want to deal with error there */
535 /*
536 check_sense();
537 if (aspi_sense[2] & SENSE_FILEMRK)
538 return;
539 */
540 return;
541 }
542
543 //----------------------------------------------------------------------------
osd_cd_play_audio_track_mscdex(UChar track)544 void osd_cd_play_audio_track_mscdex(UChar track)
545 {
546 IOCTLI cmd;
547 TRACKINFO trk;
548 PLAYREQ prq;
549 char h, m, s;
550 char h2, m2, s2;
551
552 if ((track<cdda_min_track)||(track>cdda_max_track))
553 return;
554
555 cmd.len1 = sizeof(IOCTLI);
556 cmd.unit = 0;
557 cmd.command = 3;
558 cmd.descriptor=0;
559 DW(cmd.adr_seg) = (__tb>>4);
560 DW(cmd.adr_off) = sizeof(IOCTLI);
561 DW(cmd.len2) = 7;
562 DW(cmd.secnum) = 0;
563 DW(cmd.ptr_seg) = 0;
564 DW(cmd.ptr_off) = 0;
565 trk.control = 11;
566 trk.track = track;
567
568 dosmemput(&cmd, sizeof(IOCTLI), __tb);
569 dosmemput(&trk, sizeof(TRACKINFO), (__tb + sizeof(IOCTLI)));
570
571 memset(&_regs, 0, sizeof(_regs));
572 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
573 _regs.x.bx = 0;
574 _regs.x.cx = cdda_current_drive;
575 _regs.x.ax = 0x1510;
576 __dpmi_int(0x2f, &_regs);
577
578 dosmemget(__tb, sizeof(IOCTLI), &cmd);
579 dosmemget((__tb + sizeof(IOCTLI)), sizeof(TRACKINFO), &trk);
580
581 if (DW(cmd.status)&0x8000)
582 return;
583
584 cdda_track_start = DD(trk.loc);
585
586 // TEST
587 // printf("Track %d begins at 0x%X\n",track,cdda_track_start);
588 // TEST
589
590 if (track==cdda_max_track)
591 cdda_track_end = cdda_disk_length ;
592 else {
593 cmd.len1 = sizeof(IOCTLI);
594 cmd.unit = 0;
595 cmd.command = 3;
596 cmd.descriptor=0;
597 DW(cmd.adr_seg) = (__tb>>4);
598 DW(cmd.adr_off) = sizeof(IOCTLI);
599 DW(cmd.len2) = 7;
600 DW(cmd.secnum) = 0;
601 DW(cmd.ptr_seg) = 0;
602 DW(cmd.ptr_off) = 0;
603 trk.control = 11;
604 trk.track = track+1;
605
606 dosmemput(&cmd, sizeof(IOCTLI), __tb);
607 dosmemput(&trk, sizeof(TRACKINFO), (__tb + sizeof(IOCTLI)));
608
609 memset(&_regs, 0, sizeof(_regs));
610 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
611 _regs.x.bx = 0;
612 _regs.x.cx = cdda_current_drive;
613 _regs.x.ax = 0x1510;
614 __dpmi_int(0x2f, &_regs);
615
616 dosmemget(__tb, sizeof(IOCTLI), &cmd);
617 dosmemget((__tb + sizeof(IOCTLI)), sizeof(TRACKINFO), &trk);
618
619 if (DW(cmd.status)&0x8000)
620 return;
621
622 cdda_track_end = DD(trk.loc);
623 }
624
625 h = cdda_track_end>>24;
626 m = cdda_track_end>>16;
627 s = cdda_track_end>>8;
628
629 s -= 1;
630 if (s<0) {
631 m--;
632 s += 60;
633 if (m<0) {
634 h--;
635 m+=60;
636 }
637 }
638
639 cdda_track_end = (h<<24) + (m<<16) + (s<<8);
640
641 h2 = cdda_track_start>>24;
642 m2 = cdda_track_start>>16;
643 s2 = cdda_track_start>>8;
644
645 h -= h2;
646 m -= m2;
647 s -= s2;
648
649 if (s<0) {
650 s += 60;
651 m--;
652 }
653
654 if (m<0) {
655 m += 60;
656 h--;
657 }
658
659 prq.len = 22;
660 prq.unit = 0;
661 prq.command = 132;
662 prq.mode = 1;
663 DD(prq.loc) = cdda_track_start;
664 DD(prq.secnum) = (h*270000) + (m*4500) + (s*75);
665 cdda_loop_counter = (h*216000) + (m*3600) + (s*60);
666
667 // printf("begin = %d\nlength = %d\n",cdda_track_start, (h*270000) + (m*4500) + (s*75));
668
669 dosmemput(&prq, sizeof(PLAYREQ), __tb);
670 memset(&_regs, 0, sizeof(_regs));
671 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
672 _regs.x.bx = 0;
673 _regs.x.cx = cdda_current_drive;
674 _regs.x.ax = 0x1510;
675 __dpmi_int(0x2f, &_regs);
676 dosmemget(__tb, sizeof(PLAYREQ), &prq);
677
678 if (DW(cmd.status)&0x8000)
679 return;
680
681 cdda_current_track = track;
682 cdda_playing = 1;
683 return;
684 }
685 //----------------------------------------------------------------------------
osd_cd_length(int * min,int * sec,int * fra)686 void osd_cd_length(int* min,
687 int* sec,
688 int* fra)
689 {
690 switch (osd_cd_driver)
691 {
692 case mscdex_driver:
693 osd_cd_length_mscdex(min, sec, fra);
694 break;
695 default:
696 }
697 }
698 //----------------------------------------------------------------------------
osd_cd_length_mscdex(int * min,int * sec,int * fra)699 void osd_cd_length_mscdex(int* min,
700 int* sec,
701 int* fra)
702 {
703 Redbook2Time(cdda_disk_length,
704 min,
705 sec,
706 fra);
707 }
708 //----------------------------------------------------------------------------
osd_cd_stop_audio(void)709 void osd_cd_stop_audio(void)
710 {
711 switch (osd_cd_driver)
712 {
713 case mscdex_driver:
714 osd_cd_stop_audio_mscdex();
715 break;
716 case aspi_driver:
717 osd_cd_stop_audio_aspi();
718 break;
719
720 default:
721 }
722 }
723 //----------------------------------------------------------------------------
724 /* TODO : check the command code to pause/resume playing */
osd_cd_stop_audio_aspi(void)725 void osd_cd_stop_audio_aspi(void)
726 {
727 unsigned char *sense;
728 memset(cdb, 0, 10);
729
730 // cdb[0] = SCSI_PAUSE;
731
732 aspi_stat = aspi_exec(dat, NULL, block_size, 0, cdb, 10);
733
734 /* We may want to deal with error there */
735 /*
736 check_sense();
737 if (aspi_sense[2] & SENSE_FILEMRK)
738 return;
739 */
740 return;
741 }
742 //----------------------------------------------------------------------------
osd_cd_stop_audio_mscdex(void)743 void osd_cd_stop_audio_mscdex(void)
744 {
745 STOPREQ cmd;
746
747 cmd.len = 13;
748 cmd.unit = 0;
749 cmd.command = 133;
750 dosmemput(&cmd, sizeof(STOPREQ), __tb);
751 memset(&_regs, 0, sizeof(_regs));
752 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
753 _regs.x.bx = 0;
754 _regs.x.cx = cdda_current_drive;
755 _regs.x.ax = 0x1510;
756 __dpmi_int(0x2f, &_regs);
757
758 cdda_current_track = 0;
759 cdda_playing = 0;
760 cdda_loop_counter = 0;
761 }
762
763 //----------------------------------------------------------------------------
osd_cd_close(void)764 void osd_cd_close(void)
765 {
766 switch (osd_cd_driver)
767 {
768 case mscdex_driver:
769 osd_cd_close_mscdex();
770 break;
771 case aspi_driver:
772 osd_cd_close_aspi();
773 break;
774 default:
775 }
776 }
777 //----------------------------------------------------------------------------
osd_cd_close_aspi(void)778 void osd_cd_close_aspi(void)
779 {
780 aspi_close();
781 }
782 //----------------------------------------------------------------------------
osd_cd_close_mscdex(void)783 void osd_cd_close_mscdex(void)
784 {
785 osd_cd_stop_audio();
786 }
787 //----------------------------------------------------------------------------
788 /* TODO : implement this stuff to repeat audio tracks */
osd_cd_loop_check(void)789 void osd_cd_loop_check(void)
790 {
791 if (cdda_playing==1) {
792 cdda_loop_counter--;
793 if (cdda_loop_counter==0) {
794 osd_cd_play_audio_track(cdda_current_track);
795 }
796 }
797 }
798 /*----------------------------------------------------------------------------
799
800 void cdda_cooked_read_sector_msf(unsigned char* p,unsigned long nb_sect)
801 {
802 READREQ cmd;
803
804
805 if (!p)
806 return ;
807
808 cmd.len = 27;
809 cmd.unit = 0;
810 cmd.command = 0x80;
811
812 cmd.mode_addr = 0 ; // mode HSG
813 DW(cmd.ptr_off) = 27;
814 DW(cmd.ptr_seg) = (__tb >> 4);
815 DW(cmd.nb_to_read) = 1;
816 DD(cmd.secnum) = nb_sect;
817 cmd.mode_lect = 0 ; // cooked mode
818 cmd.interleave_size = 0; // ?
819 cmd.interleave_skip = 0; // ?
820
821 dosmemput(&cmd, sizeof(READREQ), __tb);
822 memset(&_regs, 0, sizeof(_regs));
823 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
824 _regs.x.bx = 0;
825 _regs.x.cx = cdda_current_drive;
826 _regs.x.ax = 0x1510;
827 __dpmi_int(0x2f, &_regs);
828
829 if (DW(cmd.command) & 0x8000)
830 {
831 memset(p,0,2048);
832 return ;
833 }
834
835 dosmemget(__tb+sizeof(READREQ),2048,p);
836
837 return ;
838
839 }
840 */
841 //----------------------------------------------------------------------------
osd_cd_read(unsigned char * p,unsigned long nb_sect)842 void osd_cd_read(unsigned char* p,unsigned long nb_sect)
843 {
844 switch (osd_cd_driver)
845 {
846 case mscdex_driver:
847 osd_cd_read_mscdex(p, nb_sect);
848 break;
849 case aspi_driver:
850 osd_cd_read_aspi(p, nb_sect);
851 break;
852 default:
853 }
854 }
855 //----------------------------------------------------------------------------
osd_cd_read_aspi(unsigned char * buffer,unsigned long sector)856 void osd_cd_read_aspi(unsigned char *buffer, unsigned long sector)
857 {
858 unsigned char *sense;
859 memset(cdb, 0, 10);
860
861 cdb[0] = 0x28;
862 cdb[2] = sector >> 24;
863 cdb[3] = (sector >> 16) & 0xff;
864 cdb[4] = (sector >> 8) & 0xff;
865 cdb[5] = sector & 0xff;
866 cdb[8] = 0x01;
867
868 aspi_stat = aspi_exec(dat, buffer, block_size, ASPI_RW_READ, cdb, 10);
869
870 /* We may want to deal with error there */
871 /*
872 check_sense();
873 if (aspi_sense[2] & SENSE_FILEMRK)
874 return;
875 */
876 return;
877 }
878 //----------------------------------------------------------------------------
osd_cd_read_mscdex(unsigned char * p,unsigned long nb_sect)879 void osd_cd_read_mscdex(unsigned char* p,unsigned long nb_sect)
880 {
881 READREQ cmd;
882
883
884 if (!p)
885 return ;
886
887 cmd.len = 27;
888 cmd.unit = 0;
889 cmd.command = 0x80;
890
891 cmd.mode_addr = 0 ; // 1 == mode RedBook
892 // 0 == mode MSF
893 DW(cmd.ptr_off) = 27;
894 DW(cmd.ptr_seg) = (__tb >> 4);
895 DW(cmd.nb_to_read) = 1;
896 DD(cmd.secnum) = nb_sect;
897
898 cmd.mode_lect = 0 ; // 0 == cooked mode
899 // 1 == raw mode
900 cmd.interleave_size = 0; // ?
901 cmd.interleave_skip = 0; // ?
902
903 dosmemput(&cmd, sizeof(READREQ), __tb);
904 memset(&_regs, 0, sizeof(_regs));
905 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
906 _regs.x.bx = 0;
907 _regs.x.cx = cdda_current_drive;
908 _regs.x.ax = 0x1510;
909 __dpmi_int(0x2f, &_regs);
910
911 /*
912 if (DW(cmd.command) & 0x8000)
913 {
914 memset(p,0,2048);
915 return ;
916 }
917 */
918
919 dosmemget(__tb+sizeof(READREQ),2048,p);
920
921 return ;
922
923 }
924
925
926 //----------------------------------------------------------------------------
osd_cd_nb_tracks(int * first,int * last)927 void osd_cd_nb_tracks(int* first,
928 int* last)
929 {
930 switch (osd_cd_driver)
931 {
932 case mscdex_driver:
933 osd_cd_nb_tracks_mscdex(first, last);
934 break;
935 case aspi_driver:
936 osd_cd_nb_tracks_aspi(first, last);
937 break;
938 default:
939 }
940 }
941 //----------------------------------------------------------------------------
osd_cd_nb_tracks_aspi(int * first,int * last)942 void osd_cd_nb_tracks_aspi(int* first,
943 int* last)
944 {
945 UChar *sense;
946 UChar *buffer=alloca(2048);
947
948 memset(cdb, 0, 12);
949 cdb[0] = SCSI_READ_TOC;
950 cdb[8] = 0x12;
951
952 aspi_stat = aspi_exec(dat, buffer, block_size, ASPI_RW_READ, cdb, 12);
953 /* TEST */
954 *first = buffer[2];
955 *last = buffer[3];
956 /* *first = 1;
957 *last = 2;
958 */
959 /* TODO : we may like to handle errors here */
960 /*
961 aspi_check_sense();
962 if (aspi_sense[2] & SENSE_FILEMRK)
963 return 1;
964 */
965 }
966 //----------------------------------------------------------------------------
osd_cd_nb_tracks_mscdex(int * first,int * last)967 void osd_cd_nb_tracks_mscdex(int* first,
968 int* last)
969 {
970 *first = cdda_min_track;
971 *last = cdda_max_track;
972 return ;
973 }
974 //----------------------------------------------------------------------------
osd_cd_track_info(UChar track,int * min,int * sec,int * fra,int * control)975 void osd_cd_track_info(UChar track,
976 int* min,
977 int* sec,
978 int* fra,
979 int* control)
980 {
981 switch (osd_cd_driver)
982 {
983 case mscdex_driver:
984 osd_cd_track_info_mscdex(track,
985 min,
986 sec,
987 fra,
988 control);
989 break;
990 case aspi_driver:
991 osd_cd_track_info_aspi(track,
992 min,
993 sec,
994 fra,
995 control);
996 break;
997 default:
998 }
999 }
1000 //----------------------------------------------------------------------------
osd_cd_track_info_aspi(UChar track,int * min,int * sec,int * fra,int * control)1001 void osd_cd_track_info_aspi(UChar track,
1002 int* min,
1003 int* sec,
1004 int* fra,
1005 int* control)
1006 {
1007 UChar *sense;
1008 UChar *buffer=alloca(2048);
1009
1010 memset(cdb, 0, 12);
1011 cdb[0] = SCSI_READ_TOC;
1012 cdb[1] = 2; /* MSF mode */
1013 cdb[6] = track;
1014 cdb[8] = 0x12;
1015
1016 aspi_stat = aspi_exec(dat, buffer, block_size, ASPI_RW_READ, cdb, 12);
1017
1018 Log("dos/osd_cd.c : Control for track in scsi driver for track %d is %02X\n",
1019 track,
1020 buffer[5]);
1021
1022 *min = buffer[9];
1023 *sec = buffer[10];
1024 *fra = buffer[11];
1025 *control = buffer[5] & 0x4;
1026
1027 /* TODO : we may like to handle errors here */
1028 /*
1029 aspi_check_sense();
1030 if (aspi_sense[2] & SENSE_FILEMRK)
1031 return 1;
1032 */
1033 }
1034 //----------------------------------------------------------------------------
osd_cd_track_info_mscdex(UChar track,int * min,int * sec,int * fra,int * control)1035 void osd_cd_track_info_mscdex(UChar track,
1036 int* min,
1037 int* sec,
1038 int* fra,
1039 int* control)
1040 {
1041 IOCTLI cmd;
1042 TRACKINFO trk;
1043
1044 *min = *sec = *fra = *control = 0;
1045
1046 if ((track<cdda_min_track)||(track>cdda_max_track))
1047 return ;
1048
1049 cmd.len1 = sizeof(IOCTLI);
1050 cmd.unit = 0;
1051 cmd.command = 3;
1052 cmd.descriptor=0;
1053 DW(cmd.adr_seg) = (__tb>>4);
1054 DW(cmd.adr_off) = sizeof(IOCTLI);
1055 DW(cmd.len2) = 7;
1056 DW(cmd.secnum) = 0;
1057 DW(cmd.ptr_seg) = 0;
1058 DW(cmd.ptr_off) = 0;
1059 trk.control = 11;
1060 trk.track = track;
1061
1062 dosmemput(&cmd, sizeof(IOCTLI), __tb);
1063 dosmemput(&trk, sizeof(TRACKINFO), (__tb + sizeof(IOCTLI)));
1064
1065 memset(&_regs, 0, sizeof(_regs));
1066 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
1067 _regs.x.bx = 0;
1068 _regs.x.cx = cdda_current_drive;
1069 _regs.x.ax = 0x1510;
1070 __dpmi_int(0x2f, &_regs);
1071
1072 dosmemget(__tb, sizeof(IOCTLI), &cmd);
1073 dosmemget((__tb + sizeof(IOCTLI)), sizeof(TRACKINFO), &trk);
1074
1075 if (DW(cmd.status)&0x8000)
1076 {
1077 /* memset(result,0,sizeof(TRACKINFO)); */
1078 return ;
1079 }
1080
1081 Redbook2Time(trk.loc, min, sec, fra);
1082 *control = (trk.info >> 4) & 4;
1083 Log("dos/osd_cd.c : mscdex driver report type %s for track %d\n",
1084 (*control)?"CODE":"AUDIO", track);
1085 /* memcpy(result,&trk,sizeof(TRACKINFO)); */
1086
1087 }
1088
1089 //----------------------------------------------------------------------------
osd_cd_play_audio_range(int min_from,int sec_from,int fra_from,int min_to,int sec_to,int fra_to)1090 void osd_cd_play_audio_range(int min_from,
1091 int sec_from,
1092 int fra_from,
1093 int min_to,
1094 int sec_to,
1095 int fra_to)
1096 {
1097 switch (osd_cd_driver)
1098 {
1099 case mscdex_driver:
1100 osd_cd_play_audio_range_mscdex(min_from,
1101 sec_from,
1102 fra_from,
1103 min_to,
1104 sec_to,
1105 fra_to);
1106 break;
1107 case aspi_driver:
1108 osd_cd_play_audio_range_aspi(min_from,
1109 sec_from,
1110 fra_from,
1111 min_to,
1112 sec_to,
1113 fra_to);
1114 break;
1115
1116 default:
1117 }
1118 }
1119 //----------------------------------------------------------------------------
osd_cd_play_audio_range_aspi(int min_from,int sec_from,int fra_from,int min_to,int sec_to,int fra_to)1120 void osd_cd_play_audio_range_aspi(int min_from,
1121 int sec_from,
1122 int fra_from,
1123 int min_to,
1124 int sec_to,
1125 int fra_to)
1126 {
1127 unsigned char *sense;
1128 memset(cdb, 0, 10);
1129
1130 fra_to -= fra_from;
1131 sec_to -= sec_from;
1132 min_to -= min_from;
1133
1134 if (fra_to<0)
1135 {
1136 fra_to += 75;
1137 sec_to++;
1138 }
1139
1140 if (sec_to<0)
1141 {
1142 sec_to += 60;
1143 min_to++;
1144 }
1145
1146
1147 cdb[0] = SCSI_PLAYAUDMSF;
1148 cdb[3] = min_from;
1149 cdb[4] = sec_from;
1150 cdb[5] = fra_from;
1151 cdb[6] = min_to;
1152 cdb[7] = sec_to;
1153 cdb[8] = fra_to;
1154
1155 aspi_stat = aspi_exec(dat, NULL, block_size, 0, cdb, 10);
1156
1157 /* We may want to deal with error there */
1158 /*
1159 check_sense();
1160 if (aspi_sense[2] & SENSE_FILEMRK)
1161 return;
1162 */
1163 return;
1164 }
1165
1166 //----------------------------------------------------------------------------
osd_cd_play_audio_range_mscdex(int min_from,int sec_from,int fra_from,int min_to,int sec_to,int fra_to)1167 void osd_cd_play_audio_range_mscdex(int min_from,
1168 int sec_from,
1169 int fra_from,
1170 int min_to,
1171 int sec_to,
1172 int fra_to)
1173 {
1174 PLAYREQ prq;
1175
1176 prq.len = 22;
1177 prq.unit = 0;
1178 prq.command = 132;
1179 prq.mode = 0; // 0 = mode HSG
1180 // 1 = mode RedBook
1181 DD(prq.loc) = Time2HSG(min_from, sec_from, fra_from);
1182
1183 fra_to -= fra_from;
1184 sec_to -= sec_from;
1185 min_to -= min_from;
1186
1187 if (fra_to<0)
1188 {
1189 fra_to += 75;
1190 sec_to++;
1191 }
1192
1193 if (sec_to<0)
1194 {
1195 sec_to += 60;
1196 min_to++;
1197 }
1198
1199 DD(prq.secnum) = Time2HSG(min_to, sec_to, fra_to);
1200
1201 // cdda_loop_counter = (h*216000) + (m*3600) + (s*60);
1202
1203 dosmemput(&prq, sizeof(PLAYREQ), __tb);
1204 memset(&_regs, 0, sizeof(_regs));
1205 _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
1206 _regs.x.bx = 0;
1207 _regs.x.cx = cdda_current_drive;
1208 _regs.x.ax = 0x1510;
1209 __dpmi_int(0x2f, &_regs);
1210
1211 dosmemget(__tb, sizeof(PLAYREQ), &prq);
1212
1213 /*
1214 * if (DW(cmd.status)&0x8000)
1215 * return;
1216 */
1217
1218 cdda_playing = 1;
1219 return;
1220 }
1221
1222 //----------------------------------------------------------------------------
1223 /*
1224 * void cdda_cooked_prefech_read_sector_msf(unsigned long nb_sect)
1225 * {
1226 * READREQ cmd;
1227 *
1228 * cmd.len = 27;
1229 * cmd.unit = 0;
1230 * cmd.command = 0x82;
1231 *
1232 * cmd.mode_addr = 0 ; // mode HSG
1233 * DW(cmd.ptr_off) = 0;
1234 * DW(cmd.ptr_seg) = 0;
1235 * DW(cmd.nb_to_read) = 1;
1236 * DD(cmd.secnum) = nb_sect;
1237 * cmd.mode_lect = 0 ; // cooked mode
1238 * cmd.interleave_size = 0; // ?
1239 * cmd.interleave_skip = 0; // ?
1240 *
1241 * dosmemput(&cmd, sizeof(READREQ), __tb);
1242 * memset(&_regs, 0, sizeof(_regs));
1243 * _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
1244 * _regs.x.bx = 0;
1245 * _regs.x.cx = cdda_current_drive;
1246 * _regs.x.ax = 0x1510;
1247 * __dpmi_int(0x2f, &_regs);
1248 *
1249 * return ;
1250 *
1251 * }
1252 */
1253 //----------------------------------------------------------------------------
1254 /*
1255 * void cdda_cooked_prefech_read_sector_redbook(unsigned long nb_sect)
1256 * {
1257 * READREQ cmd;
1258 *
1259 *
1260 * cmd.len = 27;
1261 * cmd.unit = 0;
1262 * cmd.command = 0x82;
1263 *
1264 * cmd.mode_addr = 1 ; // mode RedBook
1265 * DW(cmd.ptr_off) = 0;
1266 * DW(cmd.ptr_seg) = 0;
1267 * DW(cmd.nb_to_read) = 1;
1268 * DD(cmd.secnum) = nb_sect;
1269 * cmd.mode_lect = 0 ; // cooked mode
1270 * cmd.interleave_size = 0; // ?
1271 * cmd.interleave_skip = 0; // ?
1272 *
1273 * dosmemput(&cmd, sizeof(READREQ), __tb);
1274 * memset(&_regs, 0, sizeof(_regs));
1275 * _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
1276 * _regs.x.bx = 0;
1277 * _regs.x.cx = cdda_current_drive;
1278 * _regs.x.ax = 0x1510;
1279 * __dpmi_int(0x2f, &_regs);
1280 *
1281 * return ;
1282 *
1283 * }
1284 */
1285 //----------------------------------------------------------------------------
1286 /* void cdda_dos_cooked_read_sector_lba(unsigned char* p, unsigned long nb_sect)
1287 * {
1288 *
1289 * memset(&_regs, 0, sizeof(_regs));
1290 * _regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4);
1291 * _regs.x.bx = 0;
1292 * _regs.x.cx = cdda_current_drive;
1293 * _regs.x.ax = 0x1508;
1294 * _regs.x.si = nb_sect >> 16;
1295 * _regs.x.di = nb_sect & 0xFFFF;
1296 * _regs.x.dx = 1;
1297 * __dpmi_int(0x2f, &_regs);
1298 *
1299 * printf("0x%x\n",_regs.x.flags);
1300 *
1301 * if ((_regs.h.al == 15) ||
1302 * (_regs.h.al == 21))
1303 * {
1304 * printf("DRIVE NOT READABLE\n");
1305 * }
1306 *
1307 * dosmemget(__tb, 2048, p);
1308 *
1309 * }
1310 */
1311