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

📄 dosgus.h

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 H
📖 第 1 页 / 共 2 页
字号:
 * issue between gus_do_flush (...); this should not be an issue however
 * because each voice has a limited (little) set of parameters that
 * you can change (freq, vol, pan... what else?)
 *
 * The pool is a pseudo-CPU code that gets executed once per timer interrupt.
 */

/* Below are definitions for commands placed in GUS command pool */
#define PCMD_NOP			0x00	/* Traditionally ... */
#define PCMD_VOICE			0x01	/* +B: select voice */
#define PCMD_START			0x02	/* +L: start voice */
#define PCMD_STOP			0x03	/*     stop voice */
#define PCMD_FREQ			0x04	/* +W: set frequence */
#define PCMD_VOLUME			0x05	/* +W: set volume */
#define PCMD_VOLUME_PREPARE		0x06	/* +W: prepare to set volume on (soon to follow) kick */
#define PCMD_PAN			0x07	/* +B: set panning */
#define PCMD_OFFSET			0x08	/* +L: set DRAM offset */
#define PCMD_STOP_LOOP			0x09	/*     stop looping */

#define GUS_VOLCHANGE_RAMP		0x20	/* Volume change ramp speed */

/* Definition for the boolean type */
typedef unsigned char boolean;
/* Prototype for functions that do block transfers to GUS DRAM:
   flags can contain any of the following bits:
      GUS_WAVE_16BIT    - sample is 16-bit
      GUS_WAVE_UNSIGNED - do not invert sign bit while downloading
 */
typedef void (*__gus_transfer_func) (unsigned long address,
                                     unsigned char *source,
                                     unsigned long size, int flags);
typedef void (*__gus_callback) ();
typedef void (*__gus_callback_3) (unsigned int, unsigned int, unsigned int);

/* Structure used to keep track of all on-board GUS memory */
typedef struct __struct_gus_mcb {
	struct __struct_gus_mcb *next;		/* Next MCB in chain */
	struct __struct_gus_mcb *prev;		/* Previous MCB in chain */
	unsigned int addr;			/* GUS DRAM address */
	unsigned int size;			/* Memory block size */
	int free;				/* 1: block is free */
} __gus_mcb;

/* Structure defining overall GUS state/information */
typedef struct {
	unsigned int port;			/* Base I/O port (0x220, 0x240, ...) */
	unsigned int irq[2];			/* GF1 IRQ and MIDI IRQ */
	unsigned int dma[2];			/* Play / record DMA */
	unsigned int ram;			/* Memory size (K), i.e. 256, 1024 etc */
	unsigned int version;			/* GUS version (see GUS_CARD_VERSION_XXX in libgus.h */
	unsigned int freq;			/* Current mixing frequency */
	unsigned int voices;			/* Active voices (14-32) */
	unsigned int dynmask;			/* Dynamically allocated voices mask */
	unsigned int timer_base;		/* The relative timer speed in percents (def: 100) */
	volatile unsigned int t1_ticks;		/* Incremented per each timer1 tick */
	volatile unsigned int t2_ticks;		/* Incremented per each timer2 tick */
	volatile unsigned int t1_countdown;	/* t1_callback is called when this reaches zero */
	volatile unsigned int t2_countdown;	/* t2_callback is called when this reaches zero */
	unsigned int t1_multiple;		/* Timer1 handler is called once per such many ticks */
	unsigned int t2_multiple;		/* Timer2 handler is called once per such many ticks */
	irq_handle *gf1_irq;			/* The interrupt handler for GF1 events */
	dma_buffer *dma_buff;			/* Pre-allocated DMA buffer */
	__gus_callback dma_callback;		/* Routine called at end of DMA transfers */
	__gus_callback t1_callback;		/* Routine called on Timer1 events */
	__gus_callback t2_callback;		/* Routine called on Timer1 events */
	__gus_callback timer_callback;		/* Called once per TEMPO ticks */
	__gus_callback_3 wt_callback;		/* Routine called on WaveTable events */
	__gus_callback_3 vl_callback;		/* Routine called on Volume ramp events */
	__gus_mcb *mcb;				/* Chained list of memory control blocks */
	__gus_transfer_func transfer;		/* Best working function for DRAM transfer */
	gus_instrument_t *instr;		/* The list of registered instruments */
	unsigned short mixer;			/* Current mixer register state */
	unsigned char dma_rate;			/* One of GF1M_DMAR_RATEX constants defined above */
	unsigned char timer_ctl;		/* Timer control register value (2x8/2x9) */
	unsigned char timer_ctl_reg;		/* Timer control register value (GF1/0x45) */
	boolean ok;				/* Is the information below okay? */
	boolean open;				/* 1 if between gus_open() and gus_close() */
	boolean ics;				/* Is it equipped with an ICS mixer? */
	boolean ics_flipped;			/* rev 5 (3.7) has flipped R/L mixer */
	boolean codec;				/* Is it equipped with a GUS MAX codec? */
	boolean interwave;			/* GUS InterWave card */
	volatile boolean dma_active;		/* DMA is transferring data */
	volatile boolean cmd_pool_ready;	/* Flush cmd_pool during timer interrupt */
	unsigned char cmd_voice;		/* Pool selection index cache */
	unsigned int cmd_pool_top;		/* Command pool top */
	unsigned char *cmd_pool;		/* Async commands pool */
	/* The following data is for private use only by interrupt routines! */
	gus_wave_t *cur_wave[32];		/* Currently played waves */
	boolean voice_kick[32];			/* Kick wave on next volume ramp IRQ */
	unsigned int kick_offs[32];		/* Sample start position on kick */
	unsigned short cur_vol[32];		/* Current voice volumes */
	unsigned int cur_voice;			/* Current voice */
	unsigned int eow_ignore;		/* Temp ignore end-of-wave IRQ for these voices */
} __gus_state;

extern __gus_state gus;
extern void __gus_delay();

static unsigned long __gus_convert_addr16(unsigned long address)
{
	return ((address & 0x0003ffff) >> 1) | (address & ~0x0003ffff);
}

/* The XXX_slow routines cannot be used outside IRQ handler! */
static inline void __gus_outregb_slow(unsigned char reg, unsigned char value)
{
	outportb(GF1_REGSEL, reg);
	outportb(GF1_DATA_HIGH, value);
	__gus_delay();
	outportb(GF1_DATA_HIGH, value);
}

static inline void __gus_outregw_slow(unsigned char reg, unsigned short value)
{
	outportb(GF1_REGSEL, reg);
	outportw(GF1_DATA, value);
	__gus_delay();
	outportw(GF1_DATA, value);
}

static inline void __gus_outregb(unsigned char reg, unsigned char value)
{
	outportb(GF1_REGSEL, reg);
	outportb(GF1_DATA_HIGH, value);
}

static inline void __gus_outregw(unsigned char reg, unsigned short value)
{
	outportb(GF1_REGSEL, reg);
	outportw(GF1_DATA, value);
}

static inline unsigned char __gus_inregb(unsigned char reg)
{
	if (reg < 0x10)
		reg |= GF1R_READ_MASK;
	outportb(GF1_REGSEL, reg);
	return inportb(GF1_DATA_HIGH);
}

static inline unsigned short __gus_inregw(unsigned char reg)
{
	if (reg < 0x10)
		reg |= GF1R_READ_MASK;
	outportb(GF1_REGSEL, reg);
	return inportw(GF1_DATA);
}

static inline void __gus_set_dram_address(unsigned int address)
{
	__gus_outregb(GF1R_DRAM_HIGH, address >> 16);
	__gus_outregw(GF1R_DRAM_LOW, address);
}

static inline unsigned char __gus_peek(unsigned int address)
{
	__gus_set_dram_address(address);
	return inportb(GF1_DRAM);
}

static inline void __gus_poke(unsigned int address, unsigned char value)
{
	__gus_set_dram_address(address);
	outportb(GF1_DRAM, value);
}

static inline void __gus_select_voice(unsigned char voice)
{
	outportb(GF1_VOICESEL, voice);
}

static inline void __gus_set_current(unsigned char mode,
                                     unsigned long address)
{
	if (mode & GF1VC_DATA16)
		address = __gus_convert_addr16(address);
	__gus_outregw_slow(GF1R_ACC_HIGH, address >> 11);
	__gus_outregw_slow(GF1R_ACC_LOW, address << 5);
}

static inline void __gus_set_loop_start(unsigned char mode,
										unsigned long address)
{
	if (mode & GF1VC_DATA16)
		address = __gus_convert_addr16(address);
	__gus_outregw_slow(GF1R_START_HIGH, address >> 11);
	__gus_outregw_slow(GF1R_START_LOW, address << 5);
}

static inline void __gus_set_loop_end(unsigned char mode,
                                      unsigned long address)
{
	address--;
	if (mode & GF1VC_DATA16)
		address = __gus_convert_addr16(address);
	__gus_outregw_slow(GF1R_END_HIGH, address >> 11);
	__gus_outregw_slow(GF1R_END_LOW, address << 5);
}

static inline void __gus_mixer_output(boolean state)
{
	if (state)
		gus.mixer &= ~GF1M_MIXER_NO_OUTPUT;
	else
		gus.mixer |= GF1M_MIXER_NO_OUTPUT;
	outportb(GF1_MIX_CTRL, gus.mixer);
	/* Dummy read to avoid touching DMA latches */
	__gus_inregb(GF1R_BALANCE);
}

/* Inline routines for working with command pools */

/* WARNING: no bounds checking due to performance reasons */
#define __POOL_VALUE(type,value)								\
  *((unsigned type *)&gus.cmd_pool [gus.cmd_pool_top]) = value;	\
  gus.cmd_pool_top += sizeof (type);

static inline void __pool_command(unsigned char command)
{
	__POOL_VALUE(char, command);
}

static inline void __pool_command_b(unsigned char command, unsigned char arg)
{
	__POOL_VALUE(char, command);
	__POOL_VALUE(char, arg);
}

static inline void __pool_command_w(unsigned char command, unsigned short arg)
{
	__POOL_VALUE(char, command);
	__POOL_VALUE(short, arg);
}

static inline void __pool_command_l(unsigned char command, unsigned long arg)
{
	__POOL_VALUE(char, command);
	__POOL_VALUE(long, arg);
}

static inline void __pool_select_voice(unsigned char voice)
{
	if (gus.cmd_voice != voice)
		__pool_command_b(PCMD_VOICE, gus.cmd_voice = voice);
}

#undef __POOL_VALUE

#ifdef DEBUG
/* Debug dump of GUS DRAM heap */
extern void __gus_mem_dump();
#endif

#endif /* __DOSGUS_H__ */

/* ex:set ts=4: */

⌨️ 快捷键说明

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