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

📄 dosgus.c

📁 tcpmp.src.0.72RC1 优秀的多媒体播放器TCPMP的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static unsigned int __gus_mem_get_free_16(){	__gus_mcb *cur = gus.mcb;	unsigned int size = 0;	if (!gus.open)		return 0;	while (cur) {		if (cur->free) {			unsigned int size16 = cur->size;			unsigned int tmp;			/* 16-bit samples cannot cross 256K boundaries */			tmp = 0x40000 - (cur->addr & 0x3ffff);			if (size16 > tmp)				size16 = tmp;			/* 16-bit samples should be aligned on a 32-byte boundary */			size16 -= (32 - cur->addr) & 0x1f;			if (size16 > size)				size = size16;			/* Now try vice versa: skip a portion of aligned memory */			size16 =			  (cur->addr + cur->size) - ((cur->addr + 0x3ffff) & ~0x3ffff);			if ((size16 < 0x7fffffff) && (size16 > size))				size = size16;		}		cur = cur->next;	}	return size;}/* Allocate a segment of GUS DRAM for a sample with given bits per sample. * The algorithm tries to find the smallest free block that fits requested * size; but if found free block is larger by some (large) delta than * requested block size, the largest possible block is preffered. */static unsigned int __gus_mem_alloc(unsigned int size, int bits16){	__gus_mcb *cur = gus.mcb;	__gus_mcb *best_max = NULL, *best_min = NULL;	unsigned int best_max_delta = 0, best_min_delta = 0xffffffff;	unsigned int best_max_prefix = 0, best_min_prefix = 0;	unsigned int memaddr, memsize;	if (!gus.open || !size || (bits16 && size > 0x40000))		return -1;	/* Round block size up to nearest acceptable DMA bound */	if (bits16)		size = (size + 0x1f) & ~0x1f;	else		size = (size + 0x0f) & ~0x0f;	while (cur) {		if (cur->free) {			unsigned char fits = 0;			memsize = cur->size;			memaddr = cur->addr;			if (bits16) {				/* 16-bit samples cannot cross 256K boundaries */				unsigned int tmp = 256 * 1024 - (memaddr & 0x3ffff);				if (memsize > tmp)					memsize = tmp;				/* 16-bit samples should be aligned on a 32-byte boundary */				memsize -= (32 - memaddr) & 0x1f;				memaddr = (memaddr + 0x1f) & ~0x1f;			}			/* If block fits, analyze it */			if (size <= memsize)				fits = 1;			/* Look if we still can complete the request by creating a free			   block */			else if (size <= cur->size) {				/* Align start address to next 256k boundary */				unsigned int endaddr = cur->addr + cur->size;				memaddr = (cur->addr + 0x3ffff) & ~0x3ffff;				/* Can we split current block by inserting a free block at the				   beginning? */				if ((memaddr < endaddr) && (memaddr + size <= endaddr))					fits = 1;			}			if (fits) {				unsigned int size_delta = cur->size - size;				unsigned int size_prefix = memaddr - cur->addr;				if (size_delta < best_min_delta)					best_min = cur, best_min_delta =					  size_delta, best_min_prefix = size_prefix;				if (size_delta > best_max_delta)					best_max = cur, best_max_delta =					  size_delta, best_max_prefix = size_prefix;			}		}		cur = cur->next;	}	if (!best_min)		return -1;	/* If minimal block that fits is too large, use largest block that fits */	/* But if using the maximal block is going to create a small hole, forget	   it */	if ((best_max_prefix == 0)		|| (best_max_prefix >= DRAM_HOLE_THRESHOLD)		|| (best_min_prefix != 0))		if (			((best_min_delta < DRAM_HOLE_THRESHOLD) &&			 (best_max_delta >= DRAM_HOLE_THRESHOLD)) ||			((best_min_prefix > 0) && (best_min_prefix < DRAM_HOLE_THRESHOLD)			 && ((best_max_prefix == 0) ||				 (best_max_prefix > best_min_prefix))) ||			((best_min_prefix != 0) && (best_max_prefix == 0))) {			best_min = best_max;			best_min_delta = best_max_delta;			best_min_prefix = best_max_prefix;		}	/* Compute the DRAM address to return */	memaddr = best_min->addr + best_min_prefix;	if (bits16)		memaddr = (memaddr + 0x1f) & ~0x1f;	else		memaddr = (memaddr + 0x0f) & ~0x0f;	/* If we have a considerable hole at the beginning of sample,	   create a free node describing the hole */	if (memaddr - best_min->addr >= DRAM_SPLIT_THRESHOLD) {		__gus_mcb *newmcb = malloc(sizeof(__gus_mcb));		newmcb->prev = best_min->prev;		newmcb->next = best_min;		newmcb->addr = best_min->addr;		newmcb->size = memaddr - best_min->addr;		newmcb->free = 1;		best_min->addr = memaddr;		best_min->size -= newmcb->size;		best_min->prev = newmcb;		if (newmcb->prev)			newmcb->prev->next = newmcb;	}	/* Compute the size of hole at the end of block */	memsize = (best_min->addr + best_min->size) - (memaddr + size);	/* Split the block if the block is larger than requested amount */	if (memsize > DRAM_SPLIT_THRESHOLD) {		/* The next node cannot be free since free blocks are always glued		   together */		__gus_mcb *newmcb = malloc(sizeof(__gus_mcb));		best_min->size -= memsize;		newmcb->prev = best_min;		newmcb->next = best_min->next;		newmcb->addr = best_min->addr + best_min->size;		newmcb->size = memsize;		newmcb->free = 1;		if (best_min->next)			best_min->next->prev = newmcb;		best_min->next = newmcb;	}	best_min->free = 0;	return memaddr;}static void __gus_mem_free(unsigned int addr){	__gus_mcb *cur = gus.mcb;	while (cur) {		if (!cur->free && (cur->addr <= addr) &&			(cur->addr + cur->size > addr)) {			cur->free = 1;			/* If next block is free as well, link them together */			if (cur->next && cur->next->free) {				__gus_mcb *next = cur->next;				cur->size += next->size;				cur->next = next->next;				if (next->next)					next->next->prev = cur;				free(next);			}			/* If previous block is free, link current block with it */			if (cur->prev && cur->prev->free) {				cur->prev->size += cur->size;				cur->prev->next = cur->next;				if (cur->next)					cur->next->prev = cur->prev;				free(cur);			}			return;		}		cur = cur->next;	}}static void __gus_mem_pack(){}#ifdef MIKMOD_DEBUG/* Debug dump of GUS DRAM heap */void __gus_mem_dump(){	__gus_mcb *cur = gus.mcb;	fprintf(stderr, "/-- Offset --+-- Prev --+-- Size --+-- Free --\\\n");	while (cur) {		fprintf(stderr, "|  %08X  | %08X |  %6d  |   %s    |\n",				cur->addr, cur->prev ? cur->prev->addr : -1, cur->size,				cur->free ? "yes" : " no");		cur = cur->next;	}	fprintf(stderr, "\\------------+----------+----------+----------/\n");}#endif/************************************************** Middle-level routines *****/static int __gus_instrument_free(gus_instrument_t * instrument){	gus_instrument_t **cur_instr;	gus_layer_t *cur_layer;	gus_wave_t *cur_wave, *wave_head;	/* Remove the instrument from the list of registered instruments */	cur_instr = (gus_instrument_t **) & gus.instr;	while (*cur_instr) {		if (*cur_instr == instrument) {			*cur_instr = instrument->next;			goto instr_loaded;		}		cur_instr = &(*cur_instr)->next;	}	return -1;instr_loaded:	wave_head = NULL;	for (cur_layer = instrument->info.layer; cur_layer;		 cur_layer = cur_layer->next)		/* Free all waves */		for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {			if (!wave_head)				wave_head = cur_wave;			if (cur_wave->begin.memory != (unsigned int)-1)				__gus_mem_free(cur_wave->begin.memory);		}	if (wave_head)		free(wave_head);	free(instrument->info.layer);	if (instrument->name)		free(instrument->name);	free(instrument);	return 0;}static gus_instrument_t *__gus_instrument_get(int program){	gus_instrument_t *cur_instr = (gus_instrument_t *) gus.instr;	while (cur_instr) {		if (cur_instr->number.instrument == program)			return cur_instr;		cur_instr = cur_instr->next;	}	return NULL;}static gus_instrument_t *__gus_instrument_copy(gus_instrument_t * instrument){	gus_instrument_t **cur_instr, *instr;	gus_layer_t *cur_layer, *dest_layer;	gus_wave_t *cur_wave, *dest_wave;	unsigned int waves, layers;	if (!instrument || !instrument->info.layer || !gus.open)		return NULL;	if (__gus_instrument_get(instrument->number.instrument))		return NULL;	instr = malloc(sizeof(gus_instrument_t));	*instr = *instrument;	if (instrument->name)		instr->name = strdup(instrument->name);	/* Make a copy of all layers at once */	for (layers = 0, cur_layer = instrument->info.layer; cur_layer; layers++)		cur_layer = cur_layer->next;	if (!(dest_layer = instr->info.layer = malloc(sizeof(gus_layer_t) * layers))) {		if (instr->name)			free(instr->name);		free(instr);		return NULL;	}	for (waves = 0, cur_layer = instrument->info.layer; cur_layer;		 cur_layer = cur_layer->next) {		*dest_layer = *cur_layer;		dest_layer->wave = NULL;		/* Count the total number of waves */		for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next)			waves++;		if (cur_layer->next)			dest_layer->next = dest_layer + 1;		else			dest_layer->next = NULL;		dest_layer++;	}	/* Allocate memory for waves */	if (!(dest_wave = malloc(sizeof(gus_wave_t) * waves))) {		free(instr->info.layer);		if (instr->name)			free(instr->name);		free(instr);		return NULL;	}	for (cur_layer = instrument->info.layer, dest_layer = instr->info.layer;	     cur_layer; cur_layer = cur_layer->next, dest_layer = dest_layer->next)		/* Copy all waves */		for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {			if (!dest_layer->wave)				dest_layer->wave = dest_wave;			*dest_wave = *cur_wave;			/* Mark DRAM address as unallocated */			dest_wave->begin.memory = -1;			if (cur_wave->next)				dest_wave->next = (dest_wave + 1);			else				dest_wave->next = NULL;			dest_wave++;		}	/* Insert the instrument into list of registered instruments */	cur_instr = (gus_instrument_t **) & gus.instr;	while (*cur_instr)		cur_instr = &(*cur_instr)->next;	*cur_instr = instr;	return instr;}static void __gus_instruments_clear(){	gus_instrument_t *next_instr, *cur_instr = (gus_instrument_t *) gus.instr;	while (cur_instr) {		next_instr = cur_instr->next;		__gus_instrument_free(cur_instr);		cur_instr = next_instr;	}}/******************************************************* libGUS interface *****//* return value: number of GUS cards installed in system */int gus_cards(){	if (!gus.ok)		__gus_init();	return gus.ok ? 1 : 0;}int gus_info(gus_info_t * info, int reread){	if (!gus.ok)		__gus_init();	if (!gus.ok)		return -1;	strcpy(info->id, "gus0");	info->flags = (gus.ram ? GUS_STRU_INFO_F_PCM : 0);	info->version = gus.version;	info->port = gus.port;	info->irq = gus.irq[0];	info->dma1 = gus.dma[0];	info->dma2 = gus.dma[1];	info->mixing_freq = gus.freq;	info->memory_size = gus.ram * 1024;	info->memory_free = __gus_mem_get_free();	info->memory_block_8 = __gus_mem_get_free_8();	info->memory_block_16 = __gus_mem_get_free_16();	return 0;}int gus_open(int card, size_t queue_buffer_size, int non_block){	__dpmi_meminfo struct_info, pool_info;	if (!gus.ok)		__gus_init();	if (!gus.ok || gus.open || card != 0)		return -1;	/* Now lock the gus structure in memory */	struct_info.address = __djgpp_base_address + (unsigned long)&gus;	struct_info.size = sizeof(gus);	if (__dpmi_lock_linear_region(&struct_info))		return -1;	/* And hook the GF1 interrupt */	__irq_stack_count = 4;	gus.gf1_irq =	  irq_hook(gus.irq[0], gf1_irq, (long)gf1_irq_end - (long)gf1_irq);	__irq_stack_count = 1;	if (!gus.gf1_irq) {		__dpmi_unlock_linear_region(&struct_info);		return -1;	}	/* Enable the interrupt */	irq_enable(gus.gf1_irq);	if (gus.irq[0] > 7)		_irq_enable(2);	/* Allocate a DMA buffer: if we fail, we just use I/O so don't fail */	if ((gus.transfer == NULL) || (gus.transfer == __gus_transfer_dma))		gus.dma_buff = dma_allocate(gus.dma[0], GF1_DMA_BUFFER_SIZE);	else		gus.dma_buff = NULL;	/* Detect the best available RAM -> DRAM transfer function */	if (!gus.transfer) {		__gus_detect_transfer();		if (gus.transfer != __gus_transfer_dma || !gus.transfer)			dma_free(gus.dma_buff), gus.dma_buff = NULL;		/* If no transfer function worked, fail */		if (!gus.transfer) {			if (gus.dma_buff)				dma_free(gus.dma_buff);			__dpmi_unlock_linear_region(&struct_info);			irq_unhook(gus.gf1_irq);			return -1;		}	}	/* Allocate and lock command pool buffer */	if (queue_buffer_size < 64)		queue_buffer_size = 64;	if (queue_buffer_size > 16384)		queue_buffer_size = 16384;	gus.cmd_pool = malloc(queue_buffer_size);	pool_info.address = __djgpp_base_address + (unsigned long)&gus.cmd_pool;	pool_info.size = sizeof(queue_buffer_size);	if (__dpmi_lock_linear_region(&pool_info)) {		if (gus.dma_buff)			dma_free(gus.dma_buff);		__dpmi_unlock_linear_region(&struct_info);		irq_unhook(gus.gf1_irq);		return -1;	}	gus.open++;

⌨️ 快捷键说明

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