⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dosgus.c

📁 tcpmp.src.0.72RC1 优秀的多媒体播放器TCPMP的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		__gus_outregb(GF1R_DRAM_HIGH, address >> 16);		if (flags & GUS_WAVE_INVERT)			if (flags & GUS_WAVE_16BIT)				while (size64k-- && size64k--) {					__gus_outregw(GF1R_DRAM_LOW, address++);					outportb(GF1_DRAM, *source++);					__gus_outregw(GF1R_DRAM_LOW, address++);					outportb(GF1_DRAM, (*source++) ^ 0x80);			} else				while (size64k--) {					__gus_outregw(GF1R_DRAM_LOW, address++);					outportb(GF1_DRAM, (*source++) ^ 0x80);		} else			while (size64k--) {				__gus_outregw(GF1R_DRAM_LOW, address++);				outportb(GF1_DRAM, *source++);			}	}}/* Wait for DMA transfer to finish between 8-9 1/18sec timer ticks */static int __gus_wait_dma(){	unsigned long timer;	_farsetsel(_dos_ds);	timer = _farnspeekl(0x46c);	while (gus.dma_active)		if (_farnspeekl(0x46c) - timer > 8) {			/* Force DMA abort since something went wrong */			__gus_reset(0);			return -1;		}	return 0;}/* Transfer a block of data into GUS DRAM through DMA controller */static void __gus_transfer_dma(unsigned long address, unsigned char *source,                               unsigned long size, int flags){	unsigned char dma_control;	unsigned long bytes_left;	unsigned long cur_size;	unsigned long dest_addr;	if ((gus.dma[0] > 3) || (flags & GUS_WAVE_16BIT))		size = (size + 1) & ~1;	bytes_left = size;	while (bytes_left) {		__gus_wait_dma();		cur_size = gus.dma_buff->size;		if (cur_size > bytes_left)			cur_size = bytes_left;		bytes_left -= cur_size;		dest_addr = address;		if (gus.dma_buff->linear != source)			memmove(gus.dma_buff->linear, source, cur_size);		source += cur_size;		address += cur_size;		/* Disable GUS -> DMA tie */		__gus_outregb(GF1R_DMA_CONTROL, 0);		__gus_delay();		/* Set up the DMA */		dma_start(gus.dma_buff, cur_size, DMA_MODE_WRITE);		gus.dma_active = 1;		/* Reset the DMA IRQ pending bit if set */		__gus_inregb(GF1R_DMA_CONTROL);		/* The 16-bit DMA channels needs a slightly different approach */		dma_control = GF1M_DMAR_ENABLE | GF1M_DMAR_IRQ_ENABLE | gus.dma_rate;		if (gus.dma[0] > 3) {			dest_addr = __gus_convert_addr16(dest_addr);			dma_control |= GF1M_DMAR_CHAN16;		}		__gus_outregw(GF1R_DMA_ADDRESS, dest_addr >> 4);		if (flags & GUS_WAVE_16BIT)			dma_control |= GF1M_DMAR_DATA16;		if (flags & GUS_WAVE_INVERT)			dma_control |= GF1M_DMAR_TOGGLE_SIGN;		/* Tell GUS to start transfer */		__gus_outregb(GF1R_DMA_CONTROL, dma_control);	}}static void __gus_detect_version(){	unsigned char tmp;	switch (gus.version = inportb(GF1_REVISION)) {	  case 5:		gus.version = GUS_CARD_VERSION_CLASSIC_ICS;		gus.ics = 1;		gus.ics_flipped = 1;		break;	  case 6:	  case 7:	  case 8:	  case 9:		gus.version = GUS_CARD_VERSION_CLASSIC_ICS;		gus.ics = 1;		break;	  case 10:		gus.version = GUS_CARD_VERSION_MAX;		gus.codec = 1;		break;	  case 11:		gus.version = GUS_CARD_VERSION_MAX1;		gus.codec = 1;		break;	  case 0x30:		gus.version = GUS_CARD_VERSION_ACE;		break;	  case 0x50:		gus.version = GUS_CARD_VERSION_EXTREME;		break;	  case 0xff:		/* Pre-3.7 board */		outportb(GF1_REG_CTRL, 0x20);		tmp = inportb(GF1_REG_CTRL);		if ((tmp != 0xff) && (tmp & 0x06))			gus.version = GUS_CARD_VERSION_CLASSIC1;		else			gus.version = GUS_CARD_VERSION_CLASSIC;		break;	  default:		/* Hmm... unknown revision. Assume a safe Classic model */#ifdef MIKMOD_DEBUG		fprintf(stderr, "libgus: Unknown board revision (%02x)\n",				gus.version);#endif		gus.version = GUS_CARD_VERSION_CLASSIC;		break;	}}static void __gus_detect_transfer(){	unsigned char *outbuff, *inbuff;	unsigned int i, j, seed = 0x13243546;	__gus_transfer_func func;#define TRANSFER_SIZE	0x4000	outbuff = malloc(TRANSFER_SIZE);	inbuff = malloc(TRANSFER_SIZE);	/* Suppose we have an malfunctioning GUS */	gus.transfer = NULL;	for (i = (gus.dma_buff ? 0 : 4); i <= 4; i++) {		switch (i) {		  case 0:			gus.dma_rate = GF1M_DMAR_RATE0;			func = __gus_transfer_dma;			break;		  case 1:			gus.dma_rate = GF1M_DMAR_RATE1;			func = __gus_transfer_dma;			break;		  case 2:			gus.dma_rate = GF1M_DMAR_RATE2;			func = __gus_transfer_dma;			break;		  case 3:			gus.dma_rate = GF1M_DMAR_RATE3;			func = __gus_transfer_dma;			break;		  case 4:			func = __gus_transfer_io;			break;		}		/* Fill data array each time with pseudo-random values */		for (j = 0; j < TRANSFER_SIZE; j++)			outbuff[j] = seed, seed =			  ((seed + 358979323) ^ (seed >> 16)) * 314159265;		/* Transfer the random array to GUS */		/* Poke a security fence around dest block */		__gus_poke(0x100 - 1, 0xAA);		__gus_poke(0x100 - 2, 0x55);		__gus_poke(0x100 + TRANSFER_SIZE + 0, 0xAA);		__gus_poke(0x100 + TRANSFER_SIZE + 1, 0x55);		func(0x100, outbuff, TRANSFER_SIZE, 0);		if (__gus_wait_dma() == 0) {			/* Check if the security fence was not damaged */			if ((__gus_peek(0x100 - 1) != 0xAA)				|| (__gus_peek(0x100 - 2) != 0x55)				|| (__gus_peek(0x100 + TRANSFER_SIZE + 0) != 0xAA)				|| (__gus_peek(0x100 + TRANSFER_SIZE + 1) != 0x55))				continue;			/* Now check if GUS DRAM really data that we expects to be transferred */			__gus_transfer_io_in(0x100, inbuff, TRANSFER_SIZE);			if (memcmp(outbuff, inbuff, TRANSFER_SIZE) == 0) {				gus.transfer = func;				break;			}		}	}#undef TRANSFER_SIZE	free(inbuff);	free(outbuff);}static void __gus_detect_memory(){	unsigned int size;	for (size = 0; size < 1024; size += 256) {		__gus_poke(size * 1024, 0xaa);		if (__gus_peek(size * 1024) != 0xaa)			break;		__gus_poke(size * 1024, 0x55);		if (__gus_peek(size * 1024) != 0x55)			break;	}	gus.ram = size;}static void __gus_init(){	char *gusenv = getenv("ULTRASND");	memset((void *)&gus, 0, sizeof(gus));	gus.cmd_voice = -1;	if (!gusenv)		return;	sscanf(gusenv, "%x,%d,%d,%d,%d", &gus.port, &gus.dma[0], &gus.dma[1],		   &gus.irq[0], &gus.irq[1]);	/* A relaxed sanity check */	if ((gus.port < 0x100) || (gus.port > 0x1000)		|| (gus.irq[0] < 2) || (gus.irq[0] > 15)		|| (gus.irq[1] < 2) || (gus.irq[1] > 15)		|| (gus.dma[0] < 0) || (gus.dma[0] > 7)		|| (gus.dma[1] < 0) || (gus.dma[1] > 7))		return;	gus.voices = 32;	gus.timer_ctl = GF1M_MASK_TIMER1 | GF1M_MASK_TIMER2;	/* Detect if the card is really there */	if (__gus_detect() == 0)		return;	/* Detect the version of Gravis Ultrasound */	__gus_detect_version();	/* Reset the card */	__gus_reset(1);	/* Detect the amount of on-board memory */	__gus_detect_memory();	gus.ok = 1;}static void __gus_kick(gus_wave_t * wave, unsigned int wave_offset){	unsigned char vc;	vc = GF1VC_IRQ;	if (wave->format & GUS_WAVE_16BIT)		vc |= GF1VC_DATA16;	if (wave->format & GUS_WAVE_BACKWARD)		vc |= GF1VC_BACKWARD;	if (wave->format & GUS_WAVE_LOOP) {		vc |= GF1VC_LOOP_ENABLE;		if (wave->format & GUS_WAVE_BIDIR)			vc |= GF1VC_BI_LOOP;	}	__gus_set_loop_start(vc, (wave->begin.memory << 4) + wave->loop_start);	if (wave->format & GUS_WAVE_LOOP)		__gus_set_loop_end(vc, (wave->begin.memory << 4) + wave->loop_end);	else		__gus_set_loop_end(vc, (wave->begin.memory + wave->size) << 4);	__gus_set_current(vc, (wave->begin.memory << 4) + wave_offset + 100);	__gus_outregb_slow(GF1R_VOICE_CONTROL, vc);}/* Timer 1 callback function (updates voices) */static void __gus_timer_update(){	gus_wave_t *wave;	unsigned long wave_offset;	unsigned char *src, *top;	unsigned int vmask = (1 << gus.cur_voice);	if (!gus.cmd_pool_ready)		return;	__gus_select_voice(gus.cur_voice);	wave_offset = 0;	src = gus.cmd_pool;	top = gus.cmd_pool + gus.cmd_pool_top;#define GET_B	*src#define GET_W	*((unsigned short *)src)#define GET_L	*((unsigned long *)src)	while (src < top) {		__gus_delay();		switch (GET_B++) {		  case PCMD_VOICE:			__gus_select_voice(gus.cur_voice = GET_B++);			vmask = (1 << gus.cur_voice);			break;		  case PCMD_FREQ:			__gus_outregw(GF1R_FREQUENCY, GET_W++);			break;		  case PCMD_PAN:			__gus_outregb(GF1R_BALANCE, GET_B++);			break;		  case PCMD_VOLUME:			__gus_volume_ramp_to(gus.cur_vol[gus.cur_voice] =								 GET_W++, GUS_VOLCHANGE_RAMP, GF1VL_IRQ);			break;		  case PCMD_VOLUME_PREPARE:			gus.cur_vol[gus.cur_voice] = GET_W++;			break;		  case PCMD_OFFSET:			wave_offset = GET_L++;			break;		  case PCMD_START:			wave = (gus_wave_t *) GET_L++;			gus.cur_wave[gus.cur_voice] = wave;			gus.kick_offs[gus.cur_voice] = wave_offset;			if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ)) {				__gus_kick(wave, wave_offset);				__gus_volume_ramp_to(gus.cur_vol[gus.cur_voice],									 GUS_VOLCHANGE_RAMP, GF1VL_IRQ);			} else				gus.voice_kick[gus.cur_voice] = 1;			wave_offset = 0;			gus.eow_ignore |= vmask;			break;		  case PCMD_STOP:			/* If volume is close to nothing, abort immediately instead of			   ramping */			gus.cur_vol[gus.cur_voice] = 0;			gus.cur_wave[gus.cur_voice] = NULL;			if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))				__gus_stop_voice();			break;		  case PCMD_STOP_LOOP:			__gus_outregb_slow(GF1R_VOICE_CONTROL,							   (__gus_inregb(GF1R_VOICE_CONTROL) | GF1VC_IRQ)							   & ~GF1VC_LOOP_ENABLE);			__gus_outregb_slow(GF1R_VOLUME_CONTROL,							   __gus_inregb(GF1R_VOLUME_CONTROL) &							   ~GF1VL_ROLLOVER);			break;		  default:			/* Alarm! Break out immediately */			src = top;			break;		}	}#undef GET_B#undef GET_W#undef GET_L	gus.cmd_pool_ready = 0;	gus.cmd_pool_top = 0;}static void __gus_wavetable_update(unsigned int voice, unsigned int voice_ctl,								   unsigned int volume_ctl){	gus_wave_t *wave = gus.cur_wave[voice];	if (!wave || !(wave->format & GUS_WAVE_LOOP)) {		__gus_stop_voice();		gus.cur_wave[voice] = NULL;		gus.cur_vol[voice] = 0;		if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))			__gus_stop_voice();	}}static void __gus_volume_update(unsigned int voice, unsigned int voice_ctl,								unsigned int volume_ctl){	__gus_volume_ramp_to(gus.cur_vol[voice], GUS_VOLCHANGE_RAMP, GF1VL_IRQ);	if (!gus.cur_wave[voice])		__gus_stop_voice();	else if (gus.voice_kick[voice])		__gus_kick(gus.cur_wave[voice], gus.kick_offs[voice]);	gus.voice_kick[voice] = 0;}/***************************************************** GUS memory manager *****//* Mark all GUS memory as available */static void __gus_mem_clear(){	__gus_mcb *cur = gus.mcb;	while (cur) {		__gus_mcb *next = cur->next;		if (cur != gus.mcb)			free(cur);		cur = next;	}	if (!gus.mcb)		gus.mcb = malloc(sizeof(__gus_mcb));	gus.mcb->next = gus.mcb->prev = NULL;	gus.mcb->addr = 0;	gus.mcb->size = gus.ram * 1024;	gus.mcb->free = 1;}/* Return amount of free memory */static unsigned int __gus_mem_get_free(){	__gus_mcb *cur = gus.mcb;	unsigned int size = 0;	if (!gus.open)		return gus.ram * 1024;	while (cur) {		if (cur->free)			size += cur->size;		cur = cur->next;	}	return size;}/* Return largest size for a 8-bit sample */static unsigned int __gus_mem_get_free_8(){	__gus_mcb *cur = gus.mcb;	unsigned int size = 0;	if (!gus.open)		return 0;	while (cur) {		if (cur->free && (cur->size > size))			size = cur->size;		cur = cur->next;	}	return size;}/* Return largest size for a 16-bit sample */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -