home *** CD-ROM | disk | FTP | other *** search
/ modiromppu / modiromppu.iso / PROGRAMS / ORGPACKS / MPG12304.ZIP / DRV_GUS.SEE < prev    next >
Text File  |  1997-04-27  |  50KB  |  1,986 lines

  1. /*
  2.  
  3. Name:
  4. DRV_GUS.C
  5.  
  6. Description:
  7. Mikmod driver for output on Gravis Ultrasound (native mode i.e. using
  8. the onboard DRAM)
  9.  
  10. Portability:
  11.  
  12. MSDOS:    BC(y)    Watcom(y)    DJGPP(y)
  13. Win95:    n
  14. Os2:    n
  15. Linux:    n
  16.  
  17. (y) - yes
  18. (n) - no (not possible or not useful)
  19. (?) - may be possible, but not tested
  20.  
  21. */
  22. #include <dos.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <conio.h>
  26. #include "mikmod.h"
  27. #include "mirq.h"
  28.  
  29. /***************************************************************************
  30. >>>>>>>>>>>>>>>>>>>>>>>>> Lowlevel GUS defines <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  31. ***************************************************************************/
  32.  
  33. /* Special macros for Least-most sig. bytes */
  34. #define MAKE_MSW(x)     ((long)((long)(x)) << 16)
  35. #define LSW(x)          ((unsigned int)(x))
  36. #define MSW(x)          ((unsigned int)(((long)x)>>16))
  37. #define MSB(x)          (unsigned char)((unsigned int)(x)>>8)
  38. #define LSB(x)          ((unsigned char)(x))
  39.  
  40. /* Make GF1 address for direct chip i/o. */
  41. #define ADDR_HIGH(x) ((unsigned int)((unsigned int)((x>>7L)&0x1fffL)))
  42. #define ADDR_LOW(x)  ((unsigned int)((unsigned int)((x&0x7fL)<<9L)))
  43.  
  44. #define JOYSTICK_TIMER  (GUS_PORT+0x201)                /* 201 */
  45. #define JOYSTICK_DATA   (GUS_PORT+0x201)                /* 201 */
  46.  
  47. #define GF1_MIDI_CTRL   (GUS_PORT+0x100)                /* 3X0 */
  48. #define GF1_MIDI_DATA   (GUS_PORT+0x101)                /* 3X1 */
  49.  
  50. #define GF1_PAGE        (GUS_PORT+0x102)                /* 3X2 */
  51. #define GF1_REG_SELECT  (GUS_PORT+0x103)                /* 3X3 */
  52. #define GF1_VOICE_SELECT (GUS_PORT+0x102)               /* 3X3 */
  53. #define GF1_DATA_LOW    (GUS_PORT+0x104)                /* 3X4 */
  54. #define GF1_DATA_HI     (GUS_PORT+0x105)                /* 3X5 */
  55. #define GF1_IRQ_STAT    (GUS_PORT+0x006)                /* 2X6 */
  56. #define GF1_DRAM        (GUS_PORT+0x107)                /* 3X7 */
  57.  
  58. #define GF1_MIX_CTRL    (GUS_PORT+0x000)                /* 2X0 */
  59. #define GF1_TIMER_CTRL  (GUS_PORT+0x008)                /* 2X8 */
  60. #define GF1_TIMER_DATA  (GUS_PORT+0x009)                /* 2X9 */
  61. #define GF1_IRQ_CTRL    (GUS_PORT+0x00B)                /* 2XB */
  62.  
  63. /* The GF1 Hardware clock. */
  64. #define CLOCK_RATE              9878400L
  65.  
  66. /* Mixer control bits. */
  67. #define ENABLE_LINE             0x01
  68. #define ENABLE_DAC              0x02
  69. #define ENABLE_MIC              0x04
  70.  
  71. /* interrupt controller 1 */
  72. #define CNTRL_8259              0x21
  73. #define OCR_8259                0x20
  74. #define EOI                     0x20
  75. #define REARM3                  0x2F3
  76. #define REARM5                  0x2F5
  77.  
  78. /* interrupt controller 2 */
  79. #define CNTRL_M_8259            0x21
  80. #define CNTRL_M2_8259              0xA1
  81. #define OCR_2_8259              0xA0
  82.  
  83. #define DMA_CONTROL             0x41
  84. #define SET_DMA_ADDRESS         0x42
  85. #define SET_DRAM_LOW            0x43
  86. #define SET_DRAM_HIGH           0x44
  87.  
  88. #define TIMER_CONTROL           0x45
  89. #define TIMER1                  0x46
  90. #define TIMER2                  0x47
  91.  
  92. #define SET_SAMPLE_RATE         0x48
  93. #define SAMPLE_CONTROL          0x49
  94.  
  95. #define SET_JOYSTICK            0x4B
  96. #define MASTER_RESET            0x4C
  97.  
  98. /* Voice register mapping. */
  99. #define SET_CONTROL                     0x00
  100. #define SET_FREQUENCY           0x01
  101. #define SET_START_HIGH          0x02
  102. #define SET_START_LOW           0x03
  103. #define SET_END_HIGH            0x04
  104. #define SET_END_LOW                     0x05
  105. #define SET_VOLUME_RATE         0x06
  106. #define SET_VOLUME_START        0x07
  107. #define SET_VOLUME_END          0x08
  108. #define SET_VOLUME                      0x09
  109. #define SET_ACC_HIGH            0x0a
  110. #define SET_ACC_LOW                     0x0b
  111. #define SET_BALANCE                     0x0c
  112. #define SET_VOLUME_CONTROL      0x0d
  113. #define SET_VOICES                      0x0e
  114.  
  115. #define GET_CONTROL                     0x80
  116. #define GET_FREQUENCY           0x81
  117. #define GET_START_HIGH          0x82
  118. #define GET_START_LOW           0x83
  119. #define GET_END_HIGH            0x84
  120. #define GET_END_LOW                     0x85
  121. #define GET_VOLUME_RATE         0x86
  122. #define GET_VOLUME_START        0x87
  123. #define GET_VOLUME_END          0x88
  124. #define GET_VOLUME                      0x89
  125. #define GET_ACC_HIGH            0x8a
  126. #define GET_ACC_LOW                     0x8b
  127. #define GET_BALANCE                     0x8c
  128. #define GET_VOLUME_CONTROL      0x8d
  129. #define GET_VOICES                      0x8e
  130. #define GET_IRQV                        0x8f
  131.  
  132. /********************************************************************
  133.  *
  134.  * MIDI defines
  135.  *
  136.  *******************************************************************/
  137.  
  138. #define MIDI_RESET      0x03
  139. #define MIDI_ENABLE_XMIT        0x20
  140. #define MIDI_ENABLE_RCV         0x80
  141.  
  142. #define MIDI_RCV_FULL           0x01
  143. #define MIDI_XMIT_EMPTY         0x02
  144. #define MIDI_FRAME_ERR          0x10
  145. #define MIDI_OVERRUN            0x20
  146. #define MIDI_IRQ_PEND           0x80
  147.  
  148. /********************************************************************
  149.  *
  150.  * JOYSTICK defines
  151.  *
  152.  *******************************************************************/
  153.  
  154. #define JOY_POSITION            0x0f
  155. #define JOY_BUTTONS                     0xf0
  156.  
  157. /********************************************************************
  158.  *
  159.  * GF1 irq/dma programmable latches
  160.  *
  161.  *******************************************************************/
  162.  
  163. /* GF1_IRQ_STATUS (port 3X6) */
  164. #define MIDI_TX_IRQ                     0x01            /* pending MIDI xmit IRQ */
  165. #define MIDI_RX_IRQ                     0x02            /* pending MIDI recv IRQ */
  166. #define GF1_TIMER1_IRQ          0x04            /* general purpose timer */
  167. #define GF1_TIMER2_IRQ          0x08            /* general purpose timer */
  168. #define WAVETABLE_IRQ           0x20            /* pending wavetable IRQ */
  169. #define ENVELOPE_IRQ            0x40            /* pending volume envelope IRQ */
  170. #define DMA_TC_IRQ                      0x80            /* pending dma tc IRQ */
  171.  
  172.  
  173. /* GF1_MIX_CTRL (port 2X0) */
  174. #define ENABLE_LINE_IN          0x01            /* 0=enable */
  175. #define ENABLE_OUTPUT           0x02            /* 0=enable */
  176. #define ENABLE_MIC_IN           0x04            /* 1=enable */
  177. #define ENABLE_GF1_IRQ          0x08            /* 1=enable */
  178. #define GF122                           0x10            /* ?? */
  179. #define ENABLE_MIDI_LOOP        0x20            /* 1=enable loop back */
  180. #define SELECT_GF1_REG          0x40            /* 0=irq latches */
  181.                                         /* 1=dma latches */
  182.  
  183. /********************************************************************
  184.  *
  185.  * GF1 global registers ($41-$4C)
  186.  *
  187.  *******************************************************************/
  188.  
  189. /* DMA control register */
  190. #define DMA_ENABLE                      0x01
  191. #define DMA_READ                        0x02            /* 1=read,0=write */
  192. #define DMA_WIDTH_16            0x04            /* 1=16 bit,0=8 bit (dma chan width)*/
  193. #define DMA_RATE                        0x18            /* 00=fast, 11=slow */
  194. #define DMA_IRQ_ENABLE          0x20            /* 1=enable */
  195. #define DMA_IRQ_PENDING         0x40            /* read */
  196. #define DMA_DATA_16                     0x40            /* write (data width) */
  197. #define DMA_TWOS_COMP           0x80            /* 1=do twos comp */
  198.  
  199. /* These are the xfer rate bits ... */
  200. #define DMA_R0          0x00            /* Fastest DMA xfer (~650khz) */
  201. #define DMA_R1          0x08            /* fastest / 2 */
  202. #define DMA_R2          0x10            /* fastest / 4 */
  203. #define DMA_R3          0x18            /* Slowest DMA xfer (fastest / 8) */
  204.  
  205. /* SAMPLE control register */
  206. #define ENABLE_ADC                      0x01
  207. #define ADC_MODE                        0x02            /* 0=mono, 1=stereo */
  208. #define ADC_DMA_WIDTH           0x04            /* 0=8 bit, 1=16 bit */
  209. #define ADC_IRQ_ENABLE          0x20            /* 1=enable */
  210. #define ADC_IRQ_PENDING         0x40            /* 1=irq pending */
  211. #define ADC_TWOS_COMP           0x80            /* 1=do twos comp */
  212.  
  213. /* RESET control register */
  214. #define GF1_MASTER_RESET        0x01            /* 0=hold in reset */
  215. #define GF1_OUTPUT_ENABLE       0x02            /* enable output */
  216. #define GF1_MASTER_IRQ          0x04            /* master IRQ enable */
  217.  
  218. /********************************************************************
  219.  *
  220.  * GF1 voice specific registers ($00 - $0E and $80-$8f)
  221.  *
  222.  *******************************************************************/
  223.  
  224. /* ($0,$80) Voice control register */
  225. #define VOICE_STOPPED           0x01            /* voice has stopped */
  226. #define STOP_VOICE                      0x02            /* stop voice */
  227. #define VC_DATA_TYPE            0x04            /* 0=8 bit,1=16 bit */
  228. #define VC_LOOP_ENABLE          0x08            /* 1=enable */
  229. #define VC_BI_LOOP                      0x10            /* 1=bi directional looping */
  230. #define VC_WAVE_IRQ                     0x20            /* 1=enable voice's wave irq */
  231. #define VC_DIRECT                       0x40            /* 0=increasing,1=decreasing */
  232. #define VC_IRQ_PENDING          0x80            /* 1=wavetable irq pending */
  233.  
  234. /* ($1,$81) Frequency control */
  235. /* Bit 0  - Unused */
  236. /* Bits 1-9 - Fractional portion */
  237. /* Bits 10-15 - Integer portion */
  238.  
  239. /* ($2,$82) Accumulator start address (high) */
  240. /* Bits 0-11 - HIGH 12 bits of address */
  241. /* Bits 12-15 - Unused */
  242.  
  243. /* ($3,$83) Accumulator start address (low) */
  244. /* Bits 0-4 - Unused */
  245. /* Bits 5-8 - Fractional portion */
  246. /* Bits 9-15 - Low 7 bits of integer portion */
  247.  
  248. /* ($4,$84) Accumulator end address (high) */
  249. /* Bits 0-11 - HIGH 12 bits of address */
  250. /* Bits 12-15 - Unused */
  251.  
  252. /* ($5,$85) Accumulator end address (low) */
  253. /* Bits 0-4 - Unused */
  254. /* Bits 5-8 - Fractional portion */
  255. /* Bits 9-15 - Low 7 bits of integer portion */
  256.  
  257.  
  258. /* ($6,$86) Volume Envelope control register */
  259. #define VL_RATE_MANTISSA                0x3f
  260. #define VL_RATE_RANGE                   0xC0
  261.  
  262. /* ($7,$87) Volume envelope start */
  263. #define VL_START_MANT                   0x0F
  264. #define VL_START_EXP                    0xF0
  265.  
  266. /* ($8,$88) Volume envelope end */
  267. #define VL_END_MANT                             0x0F
  268. #define VL_END_EXP                              0xF0
  269.  
  270. /* ($9,$89) Current volume register */
  271. /* Bits 0-3 are unused */
  272. /* Bits 4-11 - Mantissa of current volume */
  273. /* Bits 10-15 - Exponent of current volume */
  274.  
  275. /* ($A,$8A) Accumulator value (high) */
  276. /* Bits 0-12 - HIGH 12 bits of current position (a19-a7) */
  277.  
  278. /* ($B,$8B) Accumulator value (low) */
  279. /* Bits 0-8 - Fractional portion */
  280. /* Bits 9-15 - Integer portion of low adress (a6-a0) */
  281.  
  282. /* ($C,$8C) Pan (balance) position */
  283. /* Bits 0-3 - Balance position  0=full left, 0x0f=full right */
  284.  
  285. /* ($D,$8D) Volume control register */
  286. #define VOLUME_STOPPED          0x01            /* volume has stopped */
  287. #define STOP_VOLUME                     0x02            /* stop volume */
  288. #define VC_ROLLOVER                     0x04            /* Roll PAST end & gen IRQ */
  289. #define VL_LOOP_ENABLE          0x08            /* 1=enable */
  290. #define VL_BI_LOOP                      0x10            /* 1=bi directional looping */
  291. #define VL_WAVE_IRQ                     0x20            /* 1=enable voice's wave irq */
  292. #define VL_DIRECT                       0x40            /* 0=increasing,1=decreasing */
  293. #define VL_IRQ_PENDING          0x80            /* 1=wavetable irq pending */
  294.  
  295. /* ($E,$8E) # of Active voices */
  296. /* Bits 0-5 - # of active voices -1 */
  297.  
  298. /* ($F,$8F) - Sources of IRQs */
  299. /* Bits 0-4 - interrupting voice number */
  300. /* Bit 5 - Always a 1 */
  301. #define VOICE_VOLUME_IRQ        0x40            /* individual voice irq bit */
  302. #define VOICE_WAVE_IRQ          0x80            /* individual waveform irq bit */
  303.  
  304.  
  305. /***************************************************************************
  306. >>>>>>>>>>>>>>>>>>>>>>>>> Lowlevel GUS code <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  307. ***************************************************************************/
  308.  
  309. static UWORD GUS_PORT;
  310. static UBYTE GUS_VOICES;
  311. static UBYTE GUS_TIMER_CTRL;
  312. static UBYTE GUS_TIMER_MASK;
  313. static UBYTE GUS_MIX_IMAGE;
  314.  
  315. static UWORD GUS_DRAM_DMA;
  316. static UWORD GUS_ADC_DMA;
  317. static UWORD GUS_GF1_IRQ;
  318. static UWORD GUS_MIDI_IRQ;
  319. static ULONG GUS_POOL;         /* dram address of first gusmem pool node */
  320.  
  321. static UBYTE GUS_SELECT;       /* currently selected GF1 register */
  322.  
  323. static void (*GUS_TIMER1_FUNC)(void);
  324. static void (*GUS_TIMER2_FUNC)(void);
  325.  
  326. #define UltraSelect(x) outportb(GF1_REG_SELECT,GUS_SELECT=x)
  327.  
  328. #define USE_ROLLOVER 0
  329.  
  330. /***************************************************************
  331.  * This function will convert the value read from the GF1 registers
  332.  * back to a 'real' address.
  333.  ***************************************************************/
  334.  
  335. #define MAKE_MS_SWORD( x )       ((unsigned long)((unsigned long)(x)) << 16)
  336.  
  337. static ULONG make_physical_address(UWORD low,UWORD high,UBYTE mode)
  338. {
  339.     UWORD lower_16, upper_16;
  340.     ULONG ret_address, bit_19_20;
  341.  
  342.     upper_16 = high >> 9;
  343.     lower_16 = ((high & 0x01ff) << 7) | ((low >> 9) & 0x007f);
  344.  
  345.     ret_address = MAKE_MS_SWORD(upper_16) + lower_16;
  346.  
  347.     if (mode & VC_DATA_TYPE)
  348.         {
  349.         bit_19_20 = ret_address & 0xC0000;
  350.         ret_address <<= 1;
  351.         ret_address &= 0x3ffff;
  352.         ret_address |= bit_19_20;
  353.         }
  354.  
  355.     return( ret_address );
  356. }
  357.  
  358. /***************************************************************
  359.  * This function will translate the address if the dma channel
  360.  * is a 16 bit channel. This translation is not necessary for
  361.  * an 8 bit dma channel.
  362.  ***************************************************************/
  363.  
  364. static ULONG convert_to_16bit(ULONG address)
  365. /* unsigned long address;               /* 20 bit ultrasound dram address */
  366. {
  367.     ULONG hold_address;
  368.  
  369.     hold_address = address;
  370.  
  371.     /* Convert to 16 translated address. */
  372.     address = address >> 1;
  373.  
  374.     /* Zero out bit 17. */
  375.     address &= 0x0001ffffL;
  376.  
  377.     /* Reset bits 18 and 19. */
  378.     address |= (hold_address & 0x000c0000L);
  379.  
  380.     return(address);
  381. }
  382.  
  383.  
  384. static void GF1OutB(UBYTE x,UBYTE y)
  385. {
  386.     UltraSelect(x);
  387.     outportb(GF1_DATA_HI,y);
  388. }
  389.  
  390.  
  391. static void GF1OutW(UBYTE x,UWORD y)
  392. {
  393.     UltraSelect(x);
  394.     outport(GF1_DATA_LOW,y);
  395. }
  396.  
  397.  
  398. static UBYTE GF1InB(UBYTE x)
  399. {
  400.     UltraSelect(x);
  401.     return inportb(GF1_DATA_HI);
  402. }
  403.  
  404.  
  405. static UWORD GF1InW(UBYTE x)
  406. {
  407.     UltraSelect(x);
  408.     return inport(GF1_DATA_LOW);
  409. }
  410.  
  411.  
  412. static void gf1_delay(void)
  413. {
  414.     inportb(GF1_DRAM);
  415.     inportb(GF1_DRAM);
  416.     inportb(GF1_DRAM);
  417.     inportb(GF1_DRAM);
  418.     inportb(GF1_DRAM);
  419.     inportb(GF1_DRAM);
  420.     inportb(GF1_DRAM);
  421. }
  422.  
  423.  
  424. static UBYTE UltraPeek(ULONG address)
  425. {
  426.     GF1OutW(SET_DRAM_LOW,address);
  427.     GF1OutB(SET_DRAM_HIGH,(address>>16)&0xff);      /* 8 bits */
  428.     return(inportb(GF1_DRAM));
  429. }
  430.  
  431.  
  432. static void UltraPoke(ULONG address,UBYTE data)
  433. {
  434.     GF1OutW(SET_DRAM_LOW,address);
  435.     GF1OutB(SET_DRAM_HIGH,(address>>16)&0xff);
  436.     outportb(GF1_DRAM,data);
  437. }
  438.  
  439.  
  440. static void UltraPokeFast(ULONG address,UBYTE *src,ULONG size)
  441. /*
  442.     [address,size> doesn't cross 64k page boundary
  443. */
  444. {
  445.     if(!size) return;
  446.  
  447.     UltraSelect(SET_DRAM_HIGH);
  448.     outportb(GF1_DATA_HI,(address>>16)&0xff);       /* 8 bits */
  449.     UltraSelect(SET_DRAM_LOW);
  450.  
  451.     while(size--){
  452.         outport(GF1_DATA_LOW,address);
  453.         outportb(GF1_DRAM,*src);
  454.         address++;
  455.         src++;
  456.     }
  457. }
  458.  
  459.  
  460. static void UltraPokeChunk(ULONG address,UBYTE *src,ULONG size)
  461. {
  462.     ULONG todo;
  463.  
  464.     /* first 'todo' is number of bytes 'till first 64k boundary */
  465.  
  466.     todo=0x10000-(address&0xffff);
  467.     if(todo>size) todo=size;
  468.  
  469.     do{
  470.         UltraPokeFast(address,src,todo);
  471.         address+=todo;
  472.         src+=todo;
  473.         size-=todo;
  474.  
  475.         /* next 'todo' is in chunks of max 64k at once. */
  476.         todo=(size>0xffff) ? 0x10000 : size;
  477.  
  478.     } while(todo);
  479. }
  480.  
  481.  
  482. static ULONG UltraPeekLong(ULONG address)
  483. {
  484.     ULONG data;
  485.     char *s=(char *)&data;
  486.     s[0]=UltraPeek(address);
  487.     s[1]=UltraPeek(address+1);
  488.     s[2]=UltraPeek(address+2);
  489.     s[3]=UltraPeek(address+3);
  490.     return data;
  491. }
  492.  
  493.  
  494. static void UltraPokeLong(ULONG address,ULONG data)
  495. {
  496.         UltraPokeChunk(address,(UBYTE *)&data,4);
  497. }
  498.  
  499.  
  500. static void UltraEnableOutput(void)
  501. {
  502.     GUS_MIX_IMAGE &= ~ENABLE_OUTPUT;
  503.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  504. }
  505.  
  506. static void UltraDisableOutput(void)
  507. {
  508.     GUS_MIX_IMAGE |= ENABLE_OUTPUT;
  509.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  510. }
  511.  
  512. static void UltraEnableLineIn(void)
  513. {
  514.     GUS_MIX_IMAGE &= ~ENABLE_LINE_IN;
  515.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  516. }
  517.  
  518. static void UltraDisableLineIn(void)
  519. {
  520.     GUS_MIX_IMAGE |= ENABLE_LINE_IN;
  521.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  522. }
  523.  
  524. static void UltraEnableMicIn(void)
  525. {
  526.     GUS_MIX_IMAGE |= ENABLE_MIC_IN;
  527.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  528. }
  529.  
  530.  
  531. static void UltraDisableMicIn(void)
  532. {
  533.     GUS_MIX_IMAGE &= ~ENABLE_MIC_IN;
  534.     outportb(GF1_MIX_CTRL,GUS_MIX_IMAGE);
  535. }
  536.  
  537.  
  538. static void UltraReset(int voices)
  539. {
  540.     int v;
  541.  
  542.     if(voices<14) voices=14;
  543.     if(voices>32) voices=32;
  544.  
  545.     GUS_VOICES=voices;
  546.     GUS_TIMER_CTRL=0;
  547.     GUS_TIMER_MASK=0;
  548.  
  549.     UltraPokeLong(0,0);
  550.  
  551.     GF1OutB(MASTER_RESET,0x00);
  552.     for(v=0;v<10;v++) gf1_delay();
  553.  
  554.     /* Release Reset and wait */
  555.     GF1OutB(MASTER_RESET,GF1_MASTER_RESET);
  556.     for (v=0;v<10;v++) gf1_delay();
  557.  
  558.     /* Reset the MIDI port also */
  559.     outportb(GF1_MIDI_CTRL,MIDI_RESET);
  560.     for (v=0;v<10;v++) gf1_delay();
  561.     outportb(GF1_MIDI_CTRL,0x00);
  562.  
  563.     /* Clear all interrupts. */
  564.     GF1OutB(DMA_CONTROL,0x00);
  565.     GF1OutB(TIMER_CONTROL,0x00);
  566.     GF1OutB(SAMPLE_CONTROL,0x00);
  567.  
  568.     /* Set the number of active voices */
  569.     GF1OutB(SET_VOICES,((voices-1) | 0xC0));
  570.  
  571.     /* Clear interrupts on voices. */
  572.     /* Reading the status ports will clear the irqs. */
  573.  
  574.     inportb(GF1_IRQ_STAT);
  575.  
  576.     GF1InB(DMA_CONTROL);
  577.     GF1InB(SAMPLE_CONTROL);
  578.     GF1InB(GET_IRQV);
  579.  
  580.     for(v=0;v<voices;v++){
  581.  
  582.         /* Select the proper voice */
  583.         outportb(GF1_PAGE,v);
  584.  
  585.         /* Stop the voice and volume */
  586.         GF1OutB(SET_CONTROL,VOICE_STOPPED|STOP_VOICE);
  587.         GF1OutB(SET_VOLUME_CONTROL,VOLUME_STOPPED|STOP_VOLUME);
  588.  
  589.         gf1_delay(); /* Wait 4.8 micos. or more. */
  590.  
  591.         /* Initialize each voice specific registers. This is not */
  592.         /* really necessary, but is nice for completeness sake .. */
  593.         /* Each application will set up these to whatever values */
  594.         /* it needs. */
  595.  
  596.         GF1OutW(SET_FREQUENCY,0x0400);
  597.         GF1OutW(SET_START_HIGH,0);
  598.         GF1OutW(SET_START_LOW,0);
  599.         GF1OutW(SET_END_HIGH,0);
  600.         GF1OutW(SET_END_LOW,0);
  601.         GF1OutB(SET_VOLUME_RATE,0x01);
  602.         GF1OutB(SET_VOLUME_START,0x10);
  603.         GF1OutB(SET_VOLUME_END,0xe0);
  604.         GF1OutW(SET_VOLUME,0x0000);
  605.  
  606.         GF1OutW(SET_ACC_HIGH,0);
  607.         GF1OutW(SET_ACC_LOW,0);
  608.         GF1OutB(SET_BALANCE,0x07);
  609.     }
  610.  
  611.     inportb(GF1_IRQ_STAT);
  612.  
  613.     GF1InB(DMA_CONTROL);
  614.     GF1InB(SAMPLE_CONTROL);
  615.     GF1InB(GET_IRQV);
  616.  
  617.     /* Set up GF1 Chip for interrupts & enable DACs. */
  618. /*    GF1OutB(MASTER_RESET,GF1_MASTER_RESET|GF1_OUTPUT_ENABLE); */
  619.     GF1OutB(MASTER_RESET,GF1_MASTER_RESET|GF1_OUTPUT_ENABLE|GF1_MASTER_IRQ);
  620. }
  621.  
  622.  
  623. static BOOL UltraProbe(void)
  624. {
  625.     UBYTE s1,s2,t1,t2;
  626.  
  627.     /* Pull a reset on the GF1 */
  628.  
  629.     GF1OutB(MASTER_RESET,0x00);
  630.  
  631.     /* Wait a little while ... */
  632.     gf1_delay();
  633.     gf1_delay();
  634.  
  635.     /* Release Reset */
  636.     GF1OutB(MASTER_RESET,GF1_MASTER_RESET);
  637.  
  638.     gf1_delay();
  639.     gf1_delay();
  640.  
  641.     s1=UltraPeek(0); s2=UltraPeek(1);
  642.     UltraPoke(0,0xaa); t1=UltraPeek(0);
  643.     UltraPoke(1,0x55); t2=UltraPeek(1);
  644.     UltraPoke(0,s1); UltraPoke(1,s2);
  645.  
  646.     return(t1==0xaa && t2==0x55);
  647. }
  648.  
  649.  
  650.  
  651. static BOOL UltraDetect(void)
  652. {
  653.     char *ptr;
  654.  
  655.     if((ptr=getenv("ULTRASND"))==NULL) return 0;
  656.  
  657.     if(sscanf(ptr,"%hx,%hd,%hd,%hd,%hd",
  658.                 &GUS_PORT,
  659.                 &GUS_DRAM_DMA,
  660.                 &GUS_ADC_DMA,
  661.                 &GUS_GF1_IRQ,
  662.                 &GUS_MIDI_IRQ)!=5) return 0;
  663.  
  664.     return(UltraProbe());
  665. }
  666.  
  667.  
  668.  
  669.  
  670. static UBYTE dmalatch[8]       ={ 0,1,0,2,0,3,4,5 };
  671. static UBYTE irqlatch[16]      ={ 0,0,1,3,0,2,0,4,0,0,0,5,6,0,0,7 };
  672.  
  673.  
  674. static void UltraSetInterface(int dram,int adc,int gf1,int midi)
  675. /* int dram;    /* dram dma chan */
  676. /* int adc;             /* adc dma chan */
  677. /* int gf1;             /* gf1 irq # */
  678. /* int midi;    /* midi irq # */
  679. {
  680.     UBYTE gf1_irq, midi_irq,dram_dma,adc_dma;
  681.     UBYTE irq_control,dma_control;
  682.     UBYTE mix_image;
  683.  
  684.     /* Don't need to check for 0 irq #. Its latch entry = 0 */
  685.     gf1_irq =irqlatch[gf1];
  686.     midi_irq=irqlatch[midi];
  687.     midi_irq<<=3;
  688.  
  689.     dram_dma=dmalatch[dram];
  690.     adc_dma =dmalatch[adc];
  691.     adc_dma<<=3;
  692.  
  693.     irq_control=dma_control=0x0;
  694.  
  695.     mix_image=GUS_MIX_IMAGE;
  696.  
  697.     irq_control|=gf1_irq;
  698.  
  699.     if((gf1==midi) && (gf1!=0))
  700.         irq_control|=0x40;
  701.     else
  702.         irq_control|=midi_irq;
  703.  
  704.     dma_control|=dram_dma;
  705.  
  706.     if((dram==adc) && (dram!=0))
  707.         dma_control|=0x40;
  708.     else
  709.         dma_control|=adc_dma;
  710.  
  711.     /* Set up for Digital ASIC */
  712.     outportb(GUS_PORT+0x0f,0x5);
  713.     outportb(GF1_MIX_CTRL,mix_image);
  714.     outportb(GF1_IRQ_CTRL,0x0);
  715.     outportb(GUS_PORT+0x0f,0x0);
  716.  
  717.     /* First do DMA control register */
  718.     outportb(GF1_MIX_CTRL,mix_image);
  719.     outportb(GF1_IRQ_CTRL,dma_control|0x80);
  720.  
  721.     /* IRQ CONTROL REG */
  722.     outportb(GF1_MIX_CTRL,mix_image|0x40);
  723.     outportb(GF1_IRQ_CTRL,irq_control);
  724.  
  725.     /* First do DMA control register */
  726.     outportb(GF1_MIX_CTRL,mix_image);
  727.     outportb(GF1_IRQ_CTRL,dma_control);
  728.  
  729.     /* IRQ CONTROL REG */
  730.     outportb(GF1_MIX_CTRL,mix_image|0x40);
  731.     outportb(GF1_IRQ_CTRL,irq_control);
  732.  
  733.     /* IRQ CONTROL, ENABLE IRQ */
  734.     /* just to Lock out writes to irq\dma register ... */
  735.     outportb(GF1_VOICE_SELECT,0);
  736.  
  737.     /* enable output & irq, disable line & mic input */
  738.     mix_image|=0x09;
  739.     outportb(GF1_MIX_CTRL,mix_image);
  740.  
  741.     /* just to Lock out writes to irq\dma register ... */
  742.     outportb(GF1_VOICE_SELECT,0x0);
  743.  
  744.     /* put image back .... */
  745.     GUS_MIX_IMAGE=mix_image;
  746. }
  747.  
  748.  
  749. static BOOL UltraPP(ULONG address)
  750. {
  751.     UBYTE s,t;
  752.     s=UltraPeek(address);
  753.     UltraPoke(address,0xaa);
  754.     t=UltraPeek(address);
  755.     UltraPoke(address,s);
  756.     return(t==0xaa);
  757. }
  758.  
  759.  
  760. static UWORD UltraSizeDram(void)
  761. {
  762.     if(!UltraPP(0))      return 0;
  763.     if(!UltraPP(262144)) return 256;
  764.     if(!UltraPP(524288)) return 512;
  765.     if(!UltraPP(786432)) return 768;
  766.     return 1024;
  767. }
  768.  
  769.  
  770.  
  771.  
  772.  
  773. static ULONG UltraMemTotal(void)
  774. {
  775.     ULONG node=GUS_POOL,nsize,total=0;
  776.  
  777.     while(node!=0){
  778.         nsize=UltraPeekLong(node);
  779.         total+=nsize;
  780.         node=UltraPeekLong(node+4);
  781.     }
  782.     return total;
  783. }
  784.  
  785.  
  786.  
  787. static BOOL Mergeable(ULONG a,ULONG b)
  788. {
  789.     return(a && b && (a+UltraPeekLong(a))==b);
  790. }
  791.  
  792.  
  793.  
  794. static ULONG Merge(ULONG a,ULONG b)
  795. {
  796.     UltraPokeLong(a,UltraPeekLong(a)+UltraPeekLong(b));
  797.     UltraPokeLong(a+4,UltraPeekLong(b+4));
  798.     return a;
  799. }
  800.  
  801.  
  802.  
  803. static void UltraFree(ULONG size,ULONG location)
  804. {
  805.     ULONG pred=0,succ=GUS_POOL;
  806.  
  807.     if(!size) return;
  808.     size+=31;
  809.     size&=-32L;
  810.  
  811.     UltraPokeLong(location,size);
  812.  
  813.     while(succ!=0 && succ<=location){
  814.         pred=succ;
  815.         succ=UltraPeekLong(succ+4);
  816.     }
  817.  
  818.     if(pred)
  819.         UltraPokeLong(pred+4,location);
  820.     else
  821.         GUS_POOL=location;
  822.  
  823.     UltraPokeLong(location+4,succ);
  824.  
  825.     if(Mergeable(pred,location)){
  826.         location=Merge(pred,location);
  827.     }
  828.  
  829.     if(Mergeable(location,succ)){
  830.         Merge(location,succ);
  831.     }
  832. }
  833.  
  834.  
  835. /*
  836. void DumpPool(void)
  837. {
  838.     ULONG node=GUS_POOL;
  839.  
  840.     while(node!=0){
  841.         printf("Node %ld, size %ld, next %ld\n",node,UltraPeekLong(node),UltraPeekLong(node+4));
  842.         node=UltraPeekLong(node+4);
  843.     }
  844. }
  845. */
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852. static ULONG UltraMalloc(ULONG reqsize)
  853. {
  854.     ULONG curnode=GUS_POOL,cursize,newnode,newsize,pred,succ;
  855.  
  856.     if(!reqsize) return 0;
  857.  
  858.     /* round size to 32 bytes */
  859.  
  860.     reqsize+=31;
  861.     reqsize&=-32L;
  862.  
  863.     /* as long as there are nodes: */
  864.  
  865.     pred=0;
  866.  
  867.     while(curnode!=0){
  868.  
  869.         succ=UltraPeekLong(curnode+4);
  870.  
  871.         /* get current node size */
  872.  
  873.         cursize=UltraPeekLong(curnode);
  874.  
  875.         /* requested block fits? */
  876.  
  877.         if(cursize>=reqsize){
  878.  
  879.             /* it fits, so we're allocating the first
  880.                'size' bytes of this node */
  881.  
  882.             /* find new node position and size */
  883.  
  884.             newnode=curnode+reqsize;
  885.             newsize=cursize-reqsize;
  886.  
  887.             /* create a new freenode if needed: */
  888.  
  889.             if(newsize>=8){
  890.                 UltraPokeLong(newnode,newsize);
  891.                 UltraPokeLong(newnode+4,succ);
  892.                 succ=newnode;
  893.             }
  894.  
  895.             /* link prednode & succnode */
  896.  
  897.             if(pred)
  898.                 UltraPokeLong(pred+4,succ);
  899.             else
  900.                 GUS_POOL=succ;
  901.  
  902.             /* store size of allocated memory block in block itself: */
  903.  
  904.             UltraPokeLong(curnode,reqsize);
  905.             return curnode;
  906.         }
  907.  
  908.         /* doesn't fit, try next node */
  909.         curnode=succ;
  910.     }
  911.     return 0;
  912. }
  913.  
  914.  
  915.  
  916. static ULONG UltraMalloc16(ULONG reqsize)
  917. /*
  918.     Allocates a free block of gus memory, suited for 16 bit samples i.e.
  919.     smaller than 256k and doesn't cross a 256k page.
  920. */
  921. {
  922.     ULONG p,spage,epage;
  923.  
  924.     if(reqsize>262144) return 0;
  925.  
  926.     /* round size to 32 bytes */
  927.  
  928.     reqsize+=31;
  929.     reqsize&=-32L;
  930.  
  931.     p=UltraMalloc(reqsize);
  932.     spage=p>>18;
  933.     epage=(p+reqsize-1)>>18;
  934.  
  935.     if(p && spage!=epage){
  936.         ULONG newp,esize;
  937.  
  938.         /* free the second part of the block, and try again */
  939.  
  940.         esize=(p+reqsize)-(epage<<18);
  941.         UltraFree(esize,epage<<18);
  942.  
  943.         newp=UltraMalloc16(reqsize);
  944.  
  945.         /* free first part of the previous block */
  946.  
  947.         UltraFree(reqsize-esize,p);
  948.         p=newp;
  949.     }
  950.  
  951.     return p;
  952. }
  953.  
  954.  
  955.  
  956. static void UltraMemInit(void)
  957. {
  958.     UWORD memsize;
  959.     GUS_POOL=32;
  960.     memsize=UltraSizeDram();
  961.     UltraPokeLong(GUS_POOL,((ULONG)memsize<<10)-32);
  962.     UltraPokeLong(GUS_POOL+4,0);
  963. }
  964.  
  965.  
  966. static void UltraNumVoices(int voices)
  967. {
  968.     UltraDisableLineIn();
  969.     UltraDisableMicIn();
  970.     UltraDisableOutput();
  971.     UltraReset(voices);
  972.     UltraSetInterface(GUS_DRAM_DMA,GUS_ADC_DMA,GUS_GF1_IRQ,GUS_MIDI_IRQ);
  973. }
  974.  
  975.  
  976. static void interrupt gf1handler(MIRQARGS)
  977. {
  978.     UBYTE irq_source;
  979.     UBYTE oldselect=GUS_SELECT;
  980.  
  981.     while(irq_source=inportb(GF1_IRQ_STAT)){
  982.  
  983. /*        if(irq_source & DMA_TC_IRQ){
  984.             no provisions for DMA-ready irq yet
  985.         }
  986.  
  987.         if(irq_source & (MIDI_TX_IRQ|MIDI_RX_IRQ)){
  988.             no provisions for MIDI-ready irq yet
  989.         }
  990. */
  991.         if (irq_source & GF1_TIMER1_IRQ){
  992.             GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL & ~0x04);
  993.             GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL);
  994.             if(GUS_TIMER1_FUNC!=NULL) GUS_TIMER1_FUNC();
  995.         }
  996.  
  997.         if (irq_source & GF1_TIMER2_IRQ){
  998.             GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL & ~0x08);
  999.             GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL);
  1000.             if(GUS_TIMER2_FUNC!=NULL) GUS_TIMER2_FUNC();
  1001.         }
  1002.  
  1003. /*        if (irq_source & (WAVETABLE_IRQ | ENVELOPE_IRQ)){
  1004.             no wavetable or envelope irq provisions yet
  1005.         }
  1006. */
  1007.     }
  1008.  
  1009.     MIrq_EOI(GUS_GF1_IRQ);
  1010.     UltraSelect(oldselect);
  1011. }
  1012.  
  1013.  
  1014. static PVI oldhandler;
  1015. typedef void (*PFV)(void);
  1016.  
  1017.  
  1018. static PFV UltraTimer1Handler(PFV handler)
  1019. {
  1020.     PFV old=GUS_TIMER1_FUNC;
  1021.     GUS_TIMER1_FUNC=handler;
  1022.     return old;
  1023. }
  1024.  
  1025.  
  1026. static PFV UltraTimer2Handler(PFV handler)
  1027. {
  1028.     PFV old=GUS_TIMER1_FUNC;
  1029.     GUS_TIMER1_FUNC=handler;
  1030.     return old;
  1031. }
  1032.  
  1033.  
  1034. static void UltraOpen(int voices)
  1035. {
  1036.     GUS_MIX_IMAGE=0x0b;
  1037.     GUS_TIMER1_FUNC=NULL;
  1038.     GUS_TIMER2_FUNC=NULL;
  1039.  
  1040.     UltraDisableLineIn();
  1041.     UltraDisableMicIn();
  1042.     UltraDisableOutput();
  1043.  
  1044.     UltraReset(voices);
  1045.     UltraSetInterface(GUS_DRAM_DMA,GUS_ADC_DMA,GUS_GF1_IRQ,GUS_MIDI_IRQ);
  1046.     UltraMemInit();
  1047.     oldhandler=MIrq_SetHandler(GUS_GF1_IRQ,gf1handler);
  1048.     MIrq_OnOff(GUS_GF1_IRQ,1);
  1049. }
  1050.  
  1051.  
  1052. static void UltraClose(void)
  1053. {
  1054.     MIrq_OnOff(GUS_GF1_IRQ,0);
  1055.     MIrq_SetHandler(GUS_GF1_IRQ,oldhandler);
  1056.     UltraDisableOutput();
  1057.     UltraDisableLineIn();
  1058.     UltraDisableMicIn();
  1059.     UltraReset(14);
  1060. }
  1061.  
  1062.  
  1063. static void UltraSelectVoice(UBYTE voice)
  1064. {
  1065.     /* Make sure was are talking to proper voice */
  1066.     outportb(GF1_VOICE_SELECT,voice);
  1067. }
  1068.  
  1069.  
  1070.  
  1071. static void UltraSetVoiceEnd(ULONG end)
  1072. {
  1073.     ULONG phys_end;
  1074.     UBYTE data;
  1075.  
  1076.     data=GF1InB(GET_CONTROL);
  1077.  
  1078.     phys_end=(data&VC_DATA_TYPE)?convert_to_16bit(end):end;
  1079.  
  1080.     /* Set end address of buffer */
  1081.     GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
  1082.     GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
  1083.  
  1084.     data&=~(VC_IRQ_PENDING|VOICE_STOPPED|STOP_VOICE);
  1085.  
  1086.     GF1OutB(SET_CONTROL,data);
  1087.     gf1_delay();
  1088.  
  1089.     GF1OutB(SET_CONTROL,data);
  1090. }
  1091.  
  1092.  
  1093. /* The formula for this table is:
  1094.     1,000,000 / (1.619695497 * # of active voices)
  1095.  
  1096.     The 1.619695497 is calculated by knowing that 14 voices
  1097.         gives exactly 44.1 Khz. Therefore,
  1098.         1,000,000 / (X * 14) = 44100
  1099.         X = 1.619695497
  1100. */
  1101.  
  1102. static UWORD freq_divisor[19] = {
  1103.     44100,          /* 14 active voices */
  1104.     41160,          /* 15 active voices */
  1105.     38587,          /* 16 active voices */
  1106.     36317,          /* 17 active voices */
  1107.     34300,          /* 18 active voices */
  1108.     32494,          /* 19 active voices */
  1109.     30870,          /* 20 active voices */
  1110.     29400,          /* 21 active voices */
  1111.     28063,          /* 22 active voices */
  1112.     26843,          /* 23 active voices */
  1113.     25725,          /* 24 active voices */
  1114.     24696,          /* 25 active voices */
  1115.     23746,          /* 26 active voices */
  1116.     22866,          /* 27 active voices */
  1117.     22050,          /* 28 active voices */
  1118.     21289,          /* 29 active voices */
  1119.     20580,          /* 30 active voices */
  1120.     19916,          /* 31 active voices */
  1121.     19293}          /* 32 active voices */
  1122. ;
  1123.  
  1124. static void UltraSetFrequency(ULONG speed_khz)
  1125. {
  1126.     UWORD fc;
  1127.     ULONG temp;
  1128.  
  1129.     /* FC is calculated based on the # of active voices ... */
  1130.     temp=freq_divisor[GUS_VOICES-14];
  1131.  
  1132.     fc=(((speed_khz<<9L)+(temp>>1L))/temp);
  1133.     GF1OutW(SET_FREQUENCY,fc<<1);
  1134. }
  1135.  
  1136.  
  1137. static void UltraSetLoopMode(UBYTE mode)
  1138. {
  1139.     UBYTE data;
  1140.     UBYTE vmode;
  1141.  
  1142.     /* set/reset the rollover bit as per user request */
  1143.  
  1144.     vmode=GF1InB(GET_VOLUME_CONTROL);
  1145.  
  1146.     if(mode&USE_ROLLOVER)
  1147.         vmode|=VC_ROLLOVER;
  1148.     else
  1149.         vmode&=~VC_ROLLOVER;
  1150.  
  1151.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1152.     gf1_delay();
  1153.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1154.  
  1155.     data=GF1InB(GET_CONTROL);
  1156.  
  1157.     data&=~(VC_WAVE_IRQ|VC_BI_LOOP|VC_LOOP_ENABLE); /* isolate the bits */
  1158.     mode&=VC_WAVE_IRQ|VC_BI_LOOP|VC_LOOP_ENABLE;    /* no bad bits passed in */
  1159.     data|=mode;             /* turn on proper bits ... */
  1160.  
  1161.     GF1OutB(SET_CONTROL,data);
  1162.     gf1_delay();
  1163.     GF1OutB(SET_CONTROL,data);
  1164. }
  1165.  
  1166.  
  1167. static ULONG UltraReadVoice(void)
  1168. {
  1169.     UWORD count_low,count_high;
  1170.     ULONG acc;
  1171.     UBYTE mode;
  1172.  
  1173.     /* Get the high & low portion of the accumulator */
  1174.     count_high = GF1InW(GET_ACC_HIGH);
  1175.     count_low = GF1InW(GET_ACC_LOW);
  1176.  
  1177.     /* convert from UltraSound's format to a physical address */
  1178.  
  1179.     mode=GF1InB(GET_CONTROL);
  1180.  
  1181.     acc=make_physical_address(count_low,count_high,mode);
  1182.     acc&=0xfffffL;          /* Only 20 bits please ... */
  1183.  
  1184.     return(acc);
  1185. }
  1186.  
  1187.  
  1188.  
  1189. static void UltraSetVoice(ULONG location)
  1190. {
  1191.     ULONG phys_loc;
  1192.     UBYTE data;
  1193.  
  1194.     data=GF1InB(GET_CONTROL);
  1195.  
  1196.     phys_loc=(data&VC_DATA_TYPE)?convert_to_16bit(location):location;
  1197.  
  1198.     /* First set accumulator to beginning of data */
  1199.     GF1OutW(SET_ACC_HIGH,ADDR_HIGH(phys_loc));
  1200.     GF1OutW(SET_ACC_LOW,ADDR_LOW(phys_loc));
  1201. }
  1202.  
  1203.  
  1204.  
  1205. static UBYTE UltraPrimeVoice(ULONG begin,ULONG start,ULONG end,UBYTE mode)
  1206. {
  1207.     ULONG phys_start,phys_end;
  1208.     ULONG phys_begin;
  1209.     ULONG temp;
  1210.     UBYTE vmode;
  1211.  
  1212.     /* if start is greater than end, flip 'em and turn on */
  1213.     /* decrementing addresses */
  1214.     if(start>end){
  1215.         temp=start;
  1216.         start=end;
  1217.         end=temp;
  1218.         mode|=VC_DIRECT;
  1219.     }
  1220.  
  1221.     /* if 16 bit data, must convert addresses */
  1222.     if(mode&VC_DATA_TYPE){
  1223.         phys_begin = convert_to_16bit(begin);
  1224.         phys_start = convert_to_16bit(start);
  1225.         phys_end   = convert_to_16bit(end);
  1226.     }
  1227.     else{
  1228.         phys_begin = begin;
  1229.         phys_start = start;
  1230.         phys_end = end;
  1231.     }
  1232.  
  1233.     /* set/reset the rollover bit as per user request */
  1234.     vmode=GF1InB(GET_VOLUME_CONTROL);
  1235.  
  1236.     if(mode&USE_ROLLOVER)
  1237.         vmode |= VC_ROLLOVER;
  1238.     else
  1239.         vmode &= ~VC_ROLLOVER;
  1240.  
  1241.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1242.     gf1_delay();
  1243.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1244.  
  1245.     /* First set accumulator to beginning of data */
  1246.     GF1OutW(SET_ACC_LOW,ADDR_LOW(phys_begin));
  1247.     GF1OutW(SET_ACC_HIGH,ADDR_HIGH(phys_begin));
  1248.  
  1249.     /* Set start loop address of buffer */
  1250.     GF1OutW(SET_START_HIGH,ADDR_HIGH(phys_start));
  1251.     GF1OutW(SET_START_LOW,ADDR_LOW(phys_start));
  1252.  
  1253.     /* Set end address of buffer */
  1254.     GF1OutW(SET_END_HIGH,ADDR_HIGH(phys_end));
  1255.     GF1OutW(SET_END_LOW,ADDR_LOW(phys_end));
  1256.     return(mode);
  1257. }
  1258.  
  1259.  
  1260. static void UltraGoVoice(UBYTE mode)
  1261. {
  1262.     mode&=~(VOICE_STOPPED|STOP_VOICE);      /* turn 'stop' bits off ... */
  1263.  
  1264.     /* NOTE: no irq's from the voice ... */
  1265.  
  1266.     GF1OutB(SET_CONTROL,mode);
  1267.     gf1_delay();
  1268.     GF1OutB(SET_CONTROL,mode);
  1269. }
  1270.  
  1271.  
  1272. /**********************************************************************
  1273.  *
  1274.  * This function will start playing a wave out of DRAM. It assumes
  1275.  * the playback rate, volume & balance have been set up before ...
  1276.  *
  1277.  *********************************************************************/
  1278.  
  1279. static void UltraStartVoice(ULONG begin,ULONG start,ULONG end,UBYTE mode)
  1280. {
  1281.     mode=UltraPrimeVoice(begin,start,end,mode);
  1282.     UltraGoVoice(mode);
  1283. }
  1284.  
  1285.  
  1286.  
  1287. /***************************************************************
  1288.  * This function will stop a given voices output. Note that a delay
  1289.  * is necessary after the stop is issued to ensure the self-
  1290.  * modifying bits aren't a problem.
  1291.  ***************************************************************/
  1292.  
  1293. static void UltraStopVoice(void)
  1294. {
  1295.     UBYTE data;
  1296.  
  1297.     /* turn off the roll over bit first ... */
  1298.  
  1299.     data=GF1InB(GET_VOLUME_CONTROL);
  1300.     data&=~VC_ROLLOVER;
  1301.  
  1302.     GF1OutB(SET_VOLUME_CONTROL,data);
  1303.     gf1_delay();
  1304.     GF1OutB(SET_VOLUME_CONTROL,data);
  1305.  
  1306.     /* Now stop the voice  */
  1307.  
  1308.     data=GF1InB(GET_CONTROL);
  1309.     data&=~VC_WAVE_IRQ;             /* disable irq's & stop voice .. */
  1310.     data|=VOICE_STOPPED|STOP_VOICE;
  1311.  
  1312.     GF1OutB(SET_CONTROL,data);                      /* turn it off */
  1313.     gf1_delay();
  1314.     GF1OutB(SET_CONTROL,data);
  1315. }
  1316.  
  1317.  
  1318. static int UltraVoiceStopped(void)
  1319. {
  1320.     return(GF1InB(GET_CONTROL) & (VOICE_STOPPED|STOP_VOICE));
  1321. }
  1322.  
  1323.  
  1324. static void UltraSetBalance(UBYTE pan)
  1325. {
  1326.     GF1OutB(SET_BALANCE,pan&0xf);
  1327. }
  1328.  
  1329.  
  1330. static void UltraSetVolume(UWORD volume)
  1331. {
  1332.     GF1OutW(SET_VOLUME,volume<<4);
  1333. }
  1334.  
  1335.  
  1336. static UWORD UltraReadVolume(void)
  1337. {
  1338.     return(GF1InW(GET_VOLUME)>>4);
  1339. }
  1340.  
  1341.  
  1342. static void UltraStopVolume(void)
  1343. {
  1344.     UBYTE vmode;
  1345.  
  1346.     vmode=GF1InB(GET_VOLUME_CONTROL);
  1347.     vmode|=(VOLUME_STOPPED|STOP_VOLUME);
  1348.  
  1349.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1350.     gf1_delay();
  1351.     GF1OutB(SET_VOLUME_CONTROL,vmode);
  1352. }
  1353.  
  1354.  
  1355. static void UltraRampVolume(UWORD start,UWORD end,UBYTE rate,UBYTE mode)
  1356. {
  1357.     UWORD begin;
  1358.     UBYTE vmode;
  1359.  
  1360.     if(start==end) return;
  1361. /*********************************************************************
  1362.  * If the start volume is greater than the end volume, flip them and
  1363.  * turn on decreasing volume. Note that the GF1 requires that the
  1364.  * programmed start volume MUST be less than or equal to the end
  1365.  * volume.
  1366.  *********************************************************************/
  1367.     /* Don't let bad bits thru ... */
  1368.     mode&=~(VL_IRQ_PENDING|VC_ROLLOVER|STOP_VOLUME|VOLUME_STOPPED);
  1369.  
  1370.     begin = start;
  1371.  
  1372.     if(start>end){
  1373.         /* flip start & end if decreasing numbers ... */
  1374.         start = end;
  1375.         end = begin;
  1376.         mode |= VC_DIRECT;              /* decreasing volumes */
  1377.     }
  1378.  
  1379.     /* looping below 64 or greater that 4032 can cause strange things */
  1380.     if(start<64) start=64;
  1381.     if(end>4032) end=4032;
  1382.  
  1383.     GF1OutB(SET_VOLUME_RATE,rate);
  1384.     GF1OutB(SET_VOLUME_START,start>>4);
  1385.     GF1OutB(SET_VOLUME_END,end>>4);
  1386.  
  1387.     /* Also MUST set the current volume to the start volume ... */
  1388.     UltraSetVolume(begin);
  1389.  
  1390.     vmode=GF1InB(GET_VOLUME_CONTROL);
  1391.  
  1392.     if(vmode&VC_ROLLOVER) mode|=VC_ROLLOVER;
  1393.  
  1394.     /* start 'er up !!! */
  1395.     GF1OutB(SET_VOLUME_CONTROL,mode);
  1396.     gf1_delay();
  1397.     GF1OutB(SET_VOLUME_CONTROL,mode);
  1398. }
  1399.  
  1400.  
  1401. static void UltraVectorVolume(UWORD end,UBYTE rate,UBYTE mode)
  1402. {
  1403.     UltraStopVolume();
  1404.     UltraRampVolume(UltraReadVolume(),end,rate,mode);
  1405. }
  1406.  
  1407.  
  1408. static int UltraVolumeStopped(void)
  1409. {
  1410.     return(GF1InB(GET_VOLUME_CONTROL) & (VOLUME_STOPPED|STOP_VOLUME));
  1411. }
  1412.  
  1413.  
  1414. static UWORD vol_rates[19]={
  1415. 23,24,26,28,29,31,32,34,36,37,39,40,42,44,45,47,49,50,52
  1416. };
  1417.  
  1418.  
  1419. static UBYTE UltraCalcRate(UWORD start,UWORD end,ULONG mil_secs)
  1420. {
  1421.     ULONG gap,mic_secs;
  1422.     UWORD i,range,increment;
  1423.     UBYTE rate_val;
  1424.     UWORD value;
  1425.  
  1426.     gap = (start>end) ? (start-end) : (end-start);
  1427.     mic_secs = (mil_secs * 1000L)/gap;
  1428.  
  1429. /* OK. We now have the # of microseconds for each update to go from */
  1430. /* A to B in X milliseconds. See what the best fit is in the table */
  1431.  
  1432.     range = 4;
  1433.     value = vol_rates[GUS_VOICES-14];
  1434.  
  1435.     for(i=0;i<3;i++){
  1436.         if(mic_secs<value){
  1437.             range = i;
  1438.             break;
  1439.         }
  1440.         else value<<=3;
  1441.     }
  1442.  
  1443.     if(range==4){
  1444.         range = 3;
  1445.         increment = 1;
  1446.     }
  1447.     else{
  1448.         /* calculate increment value ... (round it up ?) */
  1449.         increment=(unsigned int)((value + (value>>1)) / mic_secs);
  1450.     }
  1451.  
  1452.     rate_val=range<<6;
  1453.     rate_val|=(increment&0x3F);
  1454.     return(rate_val);
  1455. }
  1456.  
  1457.  
  1458. static UWORD _gf1_volumes[512] = {
  1459.  0x0000,
  1460.  0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20,
  1461.  0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20,
  1462.  0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0,
  1463.  0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20,
  1464.  0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68,
  1465.  0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0,
  1466.  0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8,
  1467.  0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20,
  1468.  0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44,
  1469.  0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68,
  1470.  0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c,
  1471.  0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0,
  1472.  0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4,
  1473.  0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8,
  1474.  0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e,
  1475.  0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20,
  1476.  0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32,
  1477.  0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44,
  1478.  0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56,
  1479.  0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68,
  1480.  0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a,
  1481.  0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c,
  1482.  0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e,
  1483.  0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0,
  1484.  0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2,
  1485.  0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4,
  1486.  0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6,
  1487.  0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8,
  1488.  0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05,
  1489.  0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e,
  1490.  0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17,
  1491.  0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20,
  1492.  0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29,
  1493.  0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32,
  1494.  0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b,
  1495.  0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44,
  1496.  0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d,
  1497.  0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56,
  1498.  0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f,
  1499.  0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68,
  1500.  0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71,
  1501.  0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a,
  1502.  0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83,
  1503.  0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c,
  1504.  0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95,
  1505.  0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e,
  1506.  0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7,
  1507.  0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0,
  1508.  0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9,
  1509.  0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2,
  1510.  0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb,
  1511.  0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4,
  1512.  0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd,
  1513.  0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6,
  1514.  0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef,
  1515.  0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
  1516.  0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff
  1517. };
  1518.  
  1519.  
  1520. static void UltraSetLinearVolume(UWORD index)
  1521. {
  1522.     UltraSetVolume(_gf1_volumes[index]);
  1523. }
  1524.  
  1525.  
  1526. static void UltraRampLinearVolume(UWORD start_idx,UWORD end_idx,ULONG msecs,UBYTE mode)
  1527. {
  1528.     UWORD start,end;
  1529.     UBYTE rate;
  1530.  
  1531.     /* Ramp from start to end in x milliseconds */
  1532.  
  1533.     start = _gf1_volumes[start_idx];
  1534.     end   = _gf1_volumes[end_idx];
  1535.  
  1536.     /* calculate a rate to get from start to end in msec milliseconds .. */
  1537.     rate=UltraCalcRate(start,end,msecs);
  1538.     UltraRampVolume(start,end,rate,mode);
  1539. }
  1540.  
  1541.  
  1542. static void UltraVectorLinearVolume(UWORD end_idx,UBYTE rate,UBYTE mode)
  1543. {
  1544.     UltraStopVolume();
  1545.     UltraRampVolume(UltraReadVolume(),_gf1_volumes[end_idx],rate,mode);
  1546. }
  1547.  
  1548.  
  1549. static void UltraStartTimer(UBYTE timer,UBYTE time)
  1550. {
  1551.     UBYTE temp;
  1552.  
  1553.     if (timer == 1){
  1554.         GUS_TIMER_CTRL |= 0x04;
  1555.         GUS_TIMER_MASK |= 0x01;
  1556.         temp = TIMER1;
  1557.     }
  1558.     else{
  1559.         GUS_TIMER_CTRL |= 0x08;
  1560.         GUS_TIMER_MASK |= 0x02;
  1561.         temp = TIMER2;
  1562.     }
  1563.  
  1564. /*    ENTER_CRITICAL; */
  1565.  
  1566.     time = 256 - time;
  1567.  
  1568.     GF1OutB(temp,time);                            /* set timer speed */
  1569.     GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL);        /* enable timer interrupt on gf1 */
  1570.     outportb(GF1_TIMER_CTRL,0x04);                /* select timer stuff */
  1571.     outportb(GF1_TIMER_DATA,GUS_TIMER_MASK);    /* start the timers */
  1572.  
  1573. /*    LEAVE_CRITICAL; */
  1574. }
  1575.  
  1576.  
  1577. static void UltraStopTimer(int timer)
  1578. {
  1579.     if (timer == 1){
  1580.         GUS_TIMER_CTRL &= ~0x04;
  1581.         GUS_TIMER_MASK &= ~0x01;
  1582.     }
  1583.     else{
  1584.         GUS_TIMER_CTRL &= ~0x08;
  1585.         GUS_TIMER_MASK &= ~0x02;
  1586.     }
  1587.  
  1588. /*    ENTER_CRITICAL; */
  1589.  
  1590.     GF1OutB(TIMER_CONTROL,GUS_TIMER_CTRL);        /* disable timer interrupts */
  1591.     outportb(GF1_TIMER_CTRL,0x04);                /* select timer stuff */
  1592.     outportb(GF1_TIMER_DATA,GUS_TIMER_MASK | 0x80);
  1593.  
  1594. /*    LEAVE_CRITICAL; */
  1595. }
  1596.  
  1597.  
  1598. static BOOL UltraTimerStopped(UBYTE timer)
  1599. {
  1600.     UBYTE value;
  1601.     UBYTE temp;
  1602.  
  1603.     if (timer == 1)
  1604.         temp = 0x40;
  1605.     else
  1606.         temp = 0x20;
  1607.  
  1608.     value = (inportb(GF1_TIMER_CTRL)) & temp;
  1609.  
  1610.     return(value);
  1611. }
  1612.  
  1613.  
  1614. /***************************************************************************
  1615. >>>>>>>>>>>>>>>>>>>>>>>>> The actual GUS driver <<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1616. ***************************************************************************/
  1617.  
  1618.  
  1619. static ULONG Ultra[MAXSAMPLEHANDLES];
  1620. static ULONG Ultrs[MAXSAMPLEHANDLES];
  1621.  
  1622. /* Ultra[] holds the sample dram adresses
  1623.    of the samples of a module */
  1624.  
  1625. typedef struct{
  1626.     UBYTE kick;                     /* =1 -> sample has to be restarted */
  1627.     UBYTE active;                   /* =1 -> sample is playing */
  1628.     UWORD flags;                    /* 16/8 bits looping/one-shot */
  1629.     SWORD handle;                  /* identifies the sample */
  1630.     ULONG start;                    /* start index */
  1631.     ULONG size;                     /* samplesize */
  1632.     ULONG reppos;                   /* loop start */
  1633.     ULONG repend;                   /* loop end */
  1634.     ULONG frq;                      /* current frequency */
  1635.     UBYTE vol;                      /* current volume */
  1636.     UBYTE pan;                        /* current panning position */
  1637. } GHOLD;
  1638.  
  1639. static GHOLD ghld[32];
  1640.  
  1641.  
  1642. static UBYTE timeskip;
  1643. static UBYTE timecount;
  1644. static UBYTE GUS_BPM;
  1645.  
  1646.  
  1647. void UltraSetBPM(UBYTE bpm)
  1648. {
  1649.     /* The player routine has to be called (bpm*50)/125 times a second,
  1650.        so the interval between calls takes 125/(bpm*50) seconds (amazing!).
  1651.  
  1652.        The Timer1 handler has a resolution of 80 microseconds.
  1653.  
  1654.        So the timer value to program:
  1655.  
  1656.        (125/(bpm*50)) / 80e-6 = 31250/bpm
  1657.     */
  1658.     UWORD rate=31250/bpm;
  1659.  
  1660.     timeskip=0;
  1661.     timecount=0;
  1662.  
  1663.     while(rate>255){
  1664.         rate>>=1;
  1665.         timeskip++;
  1666.     }
  1667.     UltraStartTimer(1,rate);
  1668. }
  1669.  
  1670.  
  1671.  
  1672. void GUS_Update(void)
  1673. {
  1674.     UBYTE t;
  1675.     GHOLD *aud;
  1676.     UWORD vol;
  1677.     ULONG base,start,size,reppos,repend;
  1678.  
  1679.     UWORD curvol,bigvol=0,bigvoc=0;
  1680.  
  1681.     if(timecount<timeskip){
  1682.         timecount++;
  1683.         return;
  1684.     }
  1685.     timecount=0;
  1686.  
  1687.     md_player();
  1688.  
  1689.     if(GUS_BPM != md_bpm){
  1690.         UltraSetBPM(md_bpm);
  1691.         GUS_BPM=md_bpm;
  1692.     }
  1693.  
  1694.     /* ramp down voices that need to be started next */
  1695.  
  1696.     for(t=0;t<md_numchn;t++){
  1697.         UltraSelectVoice(t);
  1698.         aud=&ghld[t];
  1699.         if(aud->kick){
  1700.             curvol=UltraReadVolume();
  1701.             if(bigvol<=curvol){
  1702.                 bigvol=curvol;
  1703.                 bigvoc=t;
  1704.             }
  1705.             UltraVectorLinearVolume(0,0x3f,0);
  1706.         }
  1707.     }
  1708.  
  1709. /*      while(!UltraVolumeStopped(bigvoc)); */
  1710.  
  1711.     for(t=0;t<md_numchn;t++){
  1712.         UltraSelectVoice(t);
  1713.         aud=&ghld[t];
  1714.  
  1715.         if(aud->kick){
  1716.             aud->kick=0;
  1717.  
  1718.             base=Ultra[aud->handle];
  1719.  
  1720.             start=aud->start;
  1721.             reppos=aud->reppos;
  1722.             repend=aud->repend;
  1723.             size=aud->size;
  1724.  
  1725.             if(aud->flags&SF_16BITS){
  1726.                 start<<=1;
  1727.                 reppos<<=1;
  1728.                 repend<<=1;
  1729.                 size<<=1;
  1730.             }
  1731.  
  1732.             /* Stop current sample and start a new one */
  1733.  
  1734.             UltraStopVoice();
  1735.  
  1736.             UltraSetFrequency(aud->frq);
  1737.             UltraVectorLinearVolume(6U*aud->vol,0x3f,0);
  1738.             UltraSetBalance(aud->pan>>4);
  1739.  
  1740.             if(aud->flags&SF_LOOP){
  1741.  
  1742.                 /* Start a looping sample */
  1743.  
  1744.                 UltraStartVoice(base+start,
  1745.                                 base+reppos,
  1746.                                 base+repend,0x8|((aud->flags&SF_16BITS)?4:0)|
  1747.                                 ((aud->flags&SF_BIDI)?16:0));
  1748.             }
  1749.             else{
  1750.  
  1751.                 /* Start a one-shot sample */
  1752.  
  1753.                 UltraStartVoice(base+start,
  1754.                                 base+start,
  1755.                                 base+size+2,(aud->flags&SF_16BITS)?4:0);
  1756.             }
  1757.         }
  1758.         else{
  1759.             UltraSetFrequency(aud->frq);
  1760.             UltraVectorLinearVolume(6U*aud->vol,0x3f,0);
  1761.             UltraSetBalance(aud->pan>>4);
  1762.         }
  1763.     }
  1764. }
  1765.  
  1766.  
  1767. SWORD GUS_Load(FILE *fp,ULONG length,ULONG loopstart,ULONG loopend,UWORD flags)
  1768. /*
  1769.     callback routine for the MODLOAD module.
  1770. */
  1771. {
  1772.     int handle,t;
  1773.     long p,l;
  1774.  
  1775.     SL_Init(fp,flags,flags|SF_SIGNED);
  1776.  
  1777.     /* Find empty slot to put sample address in */
  1778.  
  1779.     for(handle=0;handle<MAXSAMPLEHANDLES;handle++){
  1780.         if(Ultra[handle]==0) break;
  1781.     }
  1782.  
  1783.     if(handle==MAXSAMPLEHANDLES){
  1784.         myerr=ERROR_OUT_OF_HANDLES;
  1785.         return -1;
  1786.     }
  1787.  
  1788.     if(flags&SF_16BITS){
  1789.         length<<=1;
  1790.         loopstart<<=1;
  1791.         loopend<<=1;
  1792.     }
  1793.  
  1794.     /* Allocate GUS dram and store the address in Ultra[handle] */
  1795.     /* Alloc 8 bytes more for anticlick measures. see below. */
  1796.  
  1797.     /* 2.04: use UltraMalloc16 to allocate 16 bit samples */
  1798.  
  1799.     if(!(Ultra[handle]=(flags&SF_16BITS) ? UltraMalloc16(length+8) : UltraMalloc(length+8) )){
  1800.         myerr=ERROR_SAMPLE_TOO_BIG;
  1801.         return -1;
  1802.     }
  1803.  
  1804.     /* Load the sample */
  1805.  
  1806.     Ultrs[handle]=length+8;
  1807.     p=Ultra[handle];
  1808.     l=length;
  1809.  
  1810.     while(l>0){
  1811.                 static UBYTE buffer[1024];
  1812.         long todo;
  1813.  
  1814.         todo=(l>1024) ? 1024 : l;
  1815.  
  1816.         SL_Load(buffer,todo);
  1817.  
  1818.         UltraPokeChunk(p,buffer,todo);
  1819.  
  1820.         p+=todo;
  1821.         l-=todo;
  1822.     }
  1823.  
  1824.     if(flags&SF_LOOP && !(flags&SF_BIDI)){  /* looping sample ? */
  1825.  
  1826.         /*      Anticlick for looping samples:
  1827.             Copy the first bytes in the loop
  1828.             beyond the end of the loop */
  1829.  
  1830.         for(t=0;t<8;t++){
  1831.             UltraPoke(Ultra[handle]+loopend+t,
  1832.                       UltraPeek(Ultra[handle]+loopstart+t));
  1833.         }
  1834.     }
  1835.     else{
  1836.  
  1837.         /*      Anticlick for one-shot samples:
  1838.             Zero the bytes beyond the end of the sample.
  1839.         */
  1840.  
  1841.         for(t=0;t<8;t++){
  1842.             UltraPoke(Ultra[handle]+length+t,0);
  1843.         }
  1844.     }
  1845.  
  1846.     return handle;
  1847. }
  1848.  
  1849.  
  1850.  
  1851. void GUS_UnLoad(SWORD handle)
  1852. /*
  1853.     callback routine to unload samples
  1854.  
  1855.     smp                     :sampleinfo of sample that is being freed
  1856. */
  1857. {
  1858.     UltraFree(Ultrs[handle],Ultra[handle]);
  1859.     Ultra[handle]=0;
  1860. }
  1861.  
  1862.  
  1863.  
  1864.  
  1865. BOOL GUS_Init(void)
  1866. {
  1867.     ULONG p1,p2;
  1868.     int irq;
  1869.  
  1870.     if(!(md_mode&DMODE_16BITS)){
  1871.         md_mode|=DMODE_16BITS;          /* gus can't do 8 bit mixing */
  1872.     }
  1873.  
  1874.     if(!(md_mode&DMODE_STEREO)){
  1875.         md_mode|=DMODE_STEREO;          /* gus can't do mono mixing */
  1876.     }
  1877.  
  1878.     if(!UltraDetect()){
  1879.         myerr="Couldn't detect gus, please check env. string";
  1880.         return 0;
  1881.     }
  1882.  
  1883.     UltraOpen(14);
  1884.     UltraTimer1Handler(GUS_Update);
  1885.  
  1886.     return 1;
  1887. }
  1888.  
  1889.  
  1890.  
  1891. void GUS_Exit(void)
  1892. {
  1893.     UltraClose();
  1894. }
  1895.  
  1896.  
  1897.  
  1898. void GUS_PlayStart(void)
  1899. {
  1900.     int t;
  1901.     for(t=0;t<md_numchn;t++){
  1902.         ghld[t].flags=0;
  1903.         ghld[t].handle=0;
  1904.         ghld[t].kick=0;
  1905.         ghld[t].active=0;
  1906.         ghld[t].frq=10000;
  1907.         ghld[t].vol=0;
  1908.         ghld[t].pan=(t&1)?0:255;
  1909.     }
  1910.     UltraNumVoices(md_numchn);
  1911.     UltraEnableOutput();
  1912.     GUS_BPM=125;
  1913.     UltraSetBPM(125);
  1914. }
  1915.  
  1916.  
  1917.  
  1918. void GUS_PlayStop(void)
  1919. {
  1920.     UltraStopTimer(1);
  1921.     UltraDisableOutput();
  1922. }
  1923.  
  1924.  
  1925. BOOL GUS_IsThere(void)
  1926. {
  1927.     return(getenv("ULTRASND")!=NULL);
  1928. }
  1929.  
  1930.  
  1931. void GUS_VoiceSetVolume(UBYTE voice,UBYTE vol)
  1932. {
  1933.     ghld[voice].vol=vol;
  1934. }
  1935.  
  1936.  
  1937. void GUS_VoiceSetFrequency(UBYTE voice,ULONG frq)
  1938. {
  1939.     ghld[voice].frq=frq;
  1940. }
  1941.  
  1942. void GUS_VoiceSetPanning(UBYTE voice,UBYTE pan)
  1943. {
  1944.     ghld[voice].pan=pan;
  1945. }
  1946.  
  1947. void GUS_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
  1948. {
  1949.     if(start>=size) return;
  1950.  
  1951.     if(flags&SF_LOOP){
  1952.         if(repend>size) repend=size;    /* repend can't be bigger than size */
  1953.     }
  1954.  
  1955.     ghld[voice].flags=flags;
  1956.     ghld[voice].handle=handle;
  1957.     ghld[voice].start=start;
  1958.     ghld[voice].size=size;
  1959.     ghld[voice].reppos=reppos;
  1960.     ghld[voice].repend=repend;
  1961.     ghld[voice].kick=1;
  1962. }
  1963.  
  1964. void GUS_Dummy(void)
  1965. {
  1966. }
  1967.  
  1968.  
  1969. DRIVER drv_gus={
  1970.     NULL,
  1971.     "Gravis Ultrasound",
  1972.     "MikMod GUS Driver v2.1 (uses gus timer interrupt)",
  1973.     GUS_IsThere,
  1974.     GUS_Load,
  1975.     GUS_UnLoad,
  1976.     GUS_Init,
  1977.     GUS_Exit,
  1978.     GUS_PlayStart,
  1979.     GUS_PlayStop,
  1980.     GUS_Dummy,
  1981.     GUS_VoiceSetVolume,
  1982.     GUS_VoiceSetFrequency,
  1983.     GUS_VoiceSetPanning,
  1984.     GUS_VoicePlay
  1985. };
  1986.