📄 dosgus.h
字号:
* 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 + -