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