www.pudn.com > ngcd080s.zip > CDAUDIO.C


/************************************** 
****   CDAUDIO.C  -  CD-DA Player  **** 
**************************************/ 
 
//-- Include files ----------------------------------------------------------- 
#include  
#include  
#include  
#include  
#include  
#include  
#include "../gui/gui.h" 
#include "../gui/rsc.h" 
#include "../ym2610/adpcm.h" 
#include "../ym2610/ym2610.h" 
 
//-- Definitions ------------------------------------------------------------- 
 
// Il s'agit d'une bidouille infame pour que DJGPP n'aligne pas les membres 
// unsigned short des structures sur des offsets pairs. (Ce qui bien sur fait 
// tout foirer et que j'ai mis deux jours a decouvrir!!) 
#define DW(id) (*((unsigned short *)(&id))) 
#define DD(id) (*((unsigned int *)(&id))) 
typedef unsigned char	BYTE; 
typedef struct { 
	BYTE	b1; 
	BYTE	b2; 
} WORD; 
 
typedef struct { 
	BYTE	b1; 
	BYTE	b2; 
	BYTE	b3; 
	BYTE	b4; 
} DWORD; 
 
//-- Structures -------------------------------------------------------------- 
typedef struct { 
	BYTE	len1; 
	BYTE 	unit; 
	BYTE	command; 
	WORD	status; 
	BYTE	reserved[8]; 
	BYTE	descriptor; 
	WORD	adr_off; 
	WORD	adr_seg; 
	WORD 	len2; 
	WORD 	secnum; 
	WORD	ptr_off; 
	WORD	ptr_seg; 
} IOCTLI; 
 
typedef struct { 
	BYTE	control; 
	BYTE	lowest; 
	BYTE	highest; 
	DWORD	total; 
} DISKINFO; 
 
typedef struct { 
	BYTE	control; 
	BYTE	track; 
	DWORD	loc; 
	BYTE	info; 
} TRACKINFO; 
 
typedef struct { 
	BYTE	len; 
	BYTE 	unit; 
	BYTE	command; 
	WORD	status; 
	BYTE	reserved[8]; 
	BYTE 	mode; 
	DWORD 	loc; 
	DWORD 	secnum; 
} PLAYREQ; 
 
typedef struct { 
	BYTE	len; 
	BYTE 	unit; 
	BYTE	command; 
	WORD	status; 
	BYTE	reserved[8]; 
} STOPREQ; 
 
typedef struct { 
	BYTE	len; 
	BYTE 	unit; 
	BYTE	command; 
	WORD	status; 
	BYTE	reserved[8]; 
	BYTE	media; 
	WORD	adr_off; 
	WORD	adr_seg; 
	WORD	bytes; 
	WORD	sector; 
	DWORD	volid; 
} VOLREQ; 
 
typedef struct { 
    BYTE	mode; 
    BYTE	input0; 
    BYTE	volume0; 
    BYTE	input1; 
    BYTE	volume1; 
    BYTE	input2; 
    BYTE	volume2; 
    BYTE	input3; 
    BYTE	volume3; 
} VOLINFO; 
 
typedef struct { 
	BYTE	control; 
	BYTE	mode; 
	DWORD	loc; 
} HEADINFO; 
 
//-- Imported Variables ------------------------------------------------------ 
extern char	*global_error[80]; 
 
//-- Private Variables ------------------------------------------------------- 
static int			cdda_min_track; 
static int			cdda_max_track; 
static int			cdda_disk_length; 
static int			cdda_track_start; 
static int			cdda_track_end; 
static int			cdda_loop_counter; 
 
//-- Public Variables -------------------------------------------------------- 
__dpmi_regs	_regs; 
int			cdda_first_drive; 
int			cdda_nb_of_drives; 
int			cdda_current_drive; 
int			cdda_current_track; 
int			cdda_playing; 
char		drive_list[26]; 
int			nb_of_drives; 
int			cdda_autoloop; 
int			cdda_volume; 
 
//-- Function Prototypes ----------------------------------------------------- 
int			cdda_init(void); 
int			cdda_play(int); 
void		cdda_stop(void); 
void		cdda_resume(void); 
int			cdda_get_volume(void); 
void		cdda_set_volume(int); 
void		cdda_shutdown(void); 
void		cdda_loop_check(void); 
int 		cdda_get_disk_info(void); 
void		cdda_build_drive_list(void); 
void		audio_setup(void); 
 
extern DATAFILE		*rsc; 
 
DIALOG audio_options[] = 
{ 
   /* (dialog proc)   (x)  (y)  (w)  (h)    (fg)    (bg)  (key)  (flags)   (d1)  (d2)            (dp) */ 
 {d_neo_border_proc,   0,   0, 240, 100, 0x0000, 0x0000,      0,      0,     0,    0,                NULL}, 
 {d_neo_fbox_proc,     2,   2, 235,   8, 0x0000, 0x10E3,      0,      0,     0,    0,                NULL}, 
 {d_text_proc,        10,   3,   0,   0, 0xFFFF, 0x10E3,      0,      0,     0,    0,     "Audio Options"}, 
 
 {d_text_proc,        10,  20,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,       "CDDA Volume"}, 
 {d_neo_slider_proc,  10,  30, 220,  10, 0xFFFF, 0x9596,      0,      0,   255,    0,                NULL}, 
  
 {d_text_proc,        10,  45,   0,   0, 0xFFFF, 0x9596,      0,      0,     0,    0,      "Sound Volume"}, 
 {d_neo_slider_proc,  10,  55, 220,  10, 0xFFFF, 0x9596,      0,      0,   255,    0,               NULL}, 
  
 {d_neo_button_proc,  87,  70,  65,  15, 0x0000, 0x0000,    'o', D_EXIT,     0,    0,               "&OK"}, 
 
 {NULL,                0,   0,   0,   0, 0x0000, 0x0000,      0,      0,     0,    0,                NULL} 
}; 
 
//---------------------------------------------------------------------------- 
int	cdda_init(void) 
{ 
	int			i, j; 
	IOCTLI 		cmd; 
	DISKINFO	di; 
 
	strcpy((char*)global_error, ""); 
 
	cdda_min_track = cdda_max_track = 0; 
	cdda_current_track = 0; 
	cdda_playing = 0; 
	cdda_loop_counter = 0; 
 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.d.eax = 0x1500; 
	_regs.d.ebx = 0; 
 
	if (__dpmi_int(0x2f, &_regs) == 0) { 
		cdda_first_drive = _regs.d.ecx; 
		cdda_nb_of_drives = _regs.d.ebx; 
		 
		cdda_build_drive_list(); 
		 
		if (cdda_current_drive==-1) 
			cdda_current_drive = cdda_first_drive; 
		else 
		{ 
			j = 0; 
			 
			for(i = 0;i < nb_of_drives;i++) 
			{ 
				if (cdda_current_drive == drive_list[i]) 
					j = 1; 
			} 
			 
			if (j==0) 
				cdda_current_drive = cdda_first_drive; 
		} 
 
		cdda_get_disk_info(); 
 
		cdda_volume = get_config_int(NULL, "cddavol", 220); 
		 
		cdda_set_volume(cdda_volume); 
 
		return 1; 
	} 
 
	strcpy((char *)global_error, "MSCDEX not present !"); 
	return	0; 
} 
 
//---------------------------------------------------------------------------- 
int cdda_get_disk_info(void) 
{ 
	IOCTLI 		cmd; 
	DISKINFO	di; 
 
	cmd.len1 = sizeof(IOCTLI); 
	cmd.unit = 0; 
	cmd.command = 3; 
	cmd.descriptor = 0; 
	DW(cmd.adr_seg) = (__tb>>4); 
	DW(cmd.adr_off) = sizeof(IOCTLI); 
	DW(cmd.len2) = 7; 
	DW(cmd.secnum) = 0; 
	DW(cmd.ptr_seg) = 0; 
	DW(cmd.ptr_off) = 0; 
	di.control = 10; 
	 
	dosmemput(&cmd, sizeof(IOCTLI), __tb); 
	dosmemput(&di, sizeof(DISKINFO), (__tb + sizeof(IOCTLI))); 
		 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	 
	dosmemget(__tb, sizeof(IOCTLI), &cmd); 
	dosmemget((__tb + sizeof(IOCTLI)), sizeof(DISKINFO), &di); 
 
	cdda_min_track = cdda_max_track = 0; 
 
	if (DW(cmd.status)&0x8000) 
		return 0; 
 
	cdda_min_track = di.lowest; 
	cdda_max_track = di.highest; 
	cdda_disk_length = DD(di.total); 
 
	return 1; 
} 
 
//---------------------------------------------------------------------------- 
void cdda_build_drive_list(void) 
{ 
	int	i; 
	 
	nb_of_drives = 0; 
 
	for(i=0;i<26;i++) 
	{ 
		_regs.x.ax = 0x150B; 
		_regs.x.cx = i; 
		__dpmi_int(0x2F, &_regs); 
		 
		if (_regs.x.ax != 0) 
		{ 
			drive_list[nb_of_drives] = i; 
			nb_of_drives++; 
		} 
	} 
} 
 
//---------------------------------------------------------------------------- 
int	cdda_play(int track) 
{ 
	IOCTLI		cmd; 
	TRACKINFO	trk; 
	PLAYREQ		prq; 
	char		h, m, s; 
	char		h2, m2, s2; 
	 
	if ((trackcdda_max_track)) 
		return 0; 
	 
	cmd.len1 = sizeof(IOCTLI); 
	cmd.unit = 0; 
	cmd.command = 3; 
	cmd.descriptor=0; 
	DW(cmd.adr_seg) = (__tb>>4); 
	DW(cmd.adr_off) = sizeof(IOCTLI); 
	DW(cmd.len2) = 7; 
	DW(cmd.secnum) = 0; 
	DW(cmd.ptr_seg) = 0; 
	DW(cmd.ptr_off) = 0; 
	trk.control = 11; 
	trk.track = track; 
 
	dosmemput(&cmd, sizeof(IOCTLI), __tb); 
	dosmemput(&trk, sizeof(TRACKINFO), (__tb + sizeof(IOCTLI))); 
	 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
 
	dosmemget(__tb, sizeof(IOCTLI), &cmd); 
	dosmemget((__tb + sizeof(IOCTLI)), sizeof(TRACKINFO), &trk); 
 
	if (DW(cmd.status)&0x8000) 
		return 0; 
		 
	cdda_track_start = DD(trk.loc); 
 
	if (track==cdda_max_track) 
		cdda_track_end = cdda_disk_length ; 
	else { 
		cmd.len1 = sizeof(IOCTLI); 
		cmd.unit = 0; 
		cmd.command = 3; 
		cmd.descriptor=0; 
		DW(cmd.adr_seg) = (__tb>>4); 
		DW(cmd.adr_off) = sizeof(IOCTLI); 
		DW(cmd.len2) = 7; 
		DW(cmd.secnum) = 0; 
		DW(cmd.ptr_seg) = 0; 
		DW(cmd.ptr_off) = 0; 
		trk.control = 11; 
		trk.track = track+1; 
	 
		dosmemput(&cmd, sizeof(IOCTLI), __tb); 
		dosmemput(&trk, sizeof(TRACKINFO), (__tb + sizeof(IOCTLI))); 
		 
		memset(&_regs, 0, sizeof(_regs)); 
		_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
		_regs.x.bx = 0; 
		_regs.x.cx = cdda_current_drive; 
		_regs.x.ax = 0x1510; 
		__dpmi_int(0x2f, &_regs); 
	 
		dosmemget(__tb, sizeof(IOCTLI), &cmd); 
		dosmemget((__tb + sizeof(IOCTLI)), sizeof(TRACKINFO), &trk); 
	 
		if (DW(cmd.status)&0x8000) 
			return 0; 
	 
		cdda_track_end = DD(trk.loc); 
	} 
	 
	h = cdda_track_end>>24; 
	m = cdda_track_end>>16; 
	s = cdda_track_end>>8; 
	 
	s -= 1; 
	if (s<0) { 
		m--; 
		s += 60; 
		if (m<0) { 
			h--; 
			m+=60; 
		} 
	} 
	 
	cdda_track_end = (h<<24) + (m<<16) + (s<<8); 
	h2 = cdda_track_start>>24; 
	m2 = cdda_track_start>>16; 
	s2 = cdda_track_start>>8; 
 
	h -= h2; 
	m -= m2; 
	s -= s2; 
	 
	if (s<0) { 
		s += 60; 
		m--; 
	} 
	 
	if (m<0) { 
		m += 60; 
		h--; 
	} 
 
	prq.len = 22; 
	prq.unit = 0; 
	prq.command = 132; 
	prq.mode = 1; 
	DD(prq.loc) = cdda_track_start; 
	DD(prq.secnum) = (h*270000) + (m*4500) + (s*75); 
	cdda_loop_counter = (h*216000) + (m*3600) + (s*60); 
	 
	dosmemput(&prq, sizeof(PLAYREQ), __tb); 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	dosmemget(__tb, sizeof(PLAYREQ), &prq); 
 
	if (DW(cmd.status)&0x8000) 
		return 0; 
	 
	cdda_current_track = track; 
	cdda_playing = 1; 
	return 1; 
} 
 
//---------------------------------------------------------------------------- 
void	cdda_stop(void) 
{ 
	STOPREQ	cmd; 
	 
	cmd.len = 13; 
	cmd.unit = 0; 
	cmd.command = 133; 
	dosmemput(&cmd, sizeof(STOPREQ), __tb); 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	 
	cdda_playing = 0; 
} 
 
//---------------------------------------------------------------------------- 
void	cdda_resume(void) 
{ 
	STOPREQ	cmd; 
	 
	cmd.len = 13; 
	cmd.unit = 0; 
	cmd.command = 136; 
	dosmemput(&cmd, sizeof(STOPREQ), __tb); 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	 
	cdda_playing = 1; 
} 
 
//---------------------------------------------------------------------------- 
void	cdda_shutdown(void) 
{ 
	cdda_stop(); 
} 
 
//---------------------------------------------------------------------------- 
void	cdda_loop_check(void) 
{ 
	if (cdda_playing==1) { 
		cdda_loop_counter--; 
		if (cdda_loop_counter==0) { 
			if (cdda_autoloop) 
				cdda_play(cdda_current_track); 
			else 
				cdda_stop(); 
		} 
	} 
} 
 
//---------------------------------------------------------------------------- 
int	cdda_get_volume(void) 
{ 
	VOLREQ	cmd; 
	VOLINFO vol; 
	 
	cmd.len = sizeof(VOLREQ); 
	cmd.unit = 0; 
	cmd.command = 3; 
	cmd.media = 0; 
	DW(cmd.sector) = 0; 
	DD(cmd.volid) = 0; 
	DW(cmd.adr_seg) = (__tb>>4); 
	DW(cmd.adr_off) = sizeof(VOLREQ); 
	DW(cmd.bytes) = 9; 
	vol.mode = 4; 
	 
	dosmemput(&cmd, sizeof(VOLREQ), __tb); 
	dosmemput(&vol, sizeof(VOLINFO), (__tb + sizeof(VOLREQ))); 
		 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	 
	dosmemget(__tb, sizeof(VOLREQ), &cmd); 
	dosmemget((__tb + sizeof(VOLREQ)), sizeof(VOLINFO), &vol); 
 
	return vol.volume0; 
} 
 
//---------------------------------------------------------------------------- 
void	cdda_set_volume(int volume) 
{ 
	VOLREQ	cmd; 
	VOLINFO vol; 
	 
	vol.mode = 3; 
	vol.input0 = 0; 
	vol.input1 = 1; 
	vol.input2 = 2; 
	vol.input3 = 3; 
	vol.volume0 = volume; 
	vol.volume1 = volume; 
	vol.volume2 = volume; 
	vol.volume3 = volume; 
 
	cmd.len = sizeof(VOLREQ); 
	cmd.unit = 0; 
	cmd.command = 12; 
	cmd.media = 0; 
	DW(cmd.adr_seg) = (__tb>>4); 
	DW(cmd.adr_off) = sizeof(VOLREQ); 
	DW(cmd.bytes) = 9; 
	 
	dosmemput(&cmd, sizeof(VOLREQ), __tb); 
	dosmemput(&vol, sizeof(VOLINFO), (__tb + sizeof(VOLREQ))); 
		 
	memset(&_regs, 0, sizeof(_regs)); 
	_regs.x.es = _regs.x.ds = _regs.x.cs = (__tb>>4); 
	_regs.x.bx = 0; 
	_regs.x.cx = cdda_current_drive; 
	_regs.x.ax = 0x1510; 
	__dpmi_int(0x2f, &_regs); 
	 
	dosmemget(__tb, sizeof(VOLREQ), &cmd); 
	dosmemget((__tb + sizeof(VOLREQ)), sizeof(VOLINFO), &vol); 
} 
 
//---------------------------------------------------------------------------- 
void audio_setup(void) 
{ 
	audio_options[4].dp = rsc[SLIDER].dat; 
	audio_options[4].d2 = cdda_get_volume(); 
 
	audio_options[6].dp = rsc[SLIDER].dat; 
	audio_options[6].d2 = sound_vol; 
 
	centre_dialog(audio_options); 
	popup_dialog(audio_options, 0); 
	 
	cdda_set_volume(audio_options[4].d2); 
	set_config_int(NULL, "cddavol", audio_options[4].d2); 
	sound_vol = audio_options[6].d2; 
	set_config_int(NULL, "soundvol", audio_options[6].d2); 
}