|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * DOS Gravis Ultrasound interface.
5: *
6: * Version 0.3
7: *
8: * (c) 1996,1997 Michael Sontheimer
9: *
10: * Please, do not change the code ! Write me an email with the bugfix,
11: * the improvement or the suggestion.
12: * My email address: [email protected]
13: *
14: */
15:
16:
17: //#define DEBUG
18:
19: #include <stdlib.h>
20: #include <stdio.h>
21: #include <string.h>
22: #include <ctype.h>
23: #include <dos.h>
24: #include <pc.h>
25: #include <sys/farptr.h>
26: #include <dpmi.h>
27: #include <go32.h>
28:
29:
30: #include "sysconfig.h"
31: #include "sysdeps.h"
32: #include "sound/gus.h"
33: #include "sound/dma.h"
34:
35:
36:
37: #ifndef TRUE
38: #define TRUE 1
39: #endif
40: #ifndef FALSE
41: #define FALSE 0
42: #endif
43:
44:
45: // GUS Ports
46:
47: #define GUS_COMMAND 0x103
48: #define GUS_DATAHI 0x105
49: #define GUS_DATALO 0x104
50: #define GUS_IRQSTATE 0x006
51: #define GUS_TIMERCTRL 0x008
52: #define GUS_TIMERDATA 0x009
53: #define GUS_VOICE 0x102
54: #define GUS_DRAM 0x107
55: #define GUS_MIXER 0x000
56: #define GUS_DMACTRL 0x00b // Beide Adressen sind identisch !!!
57: #define GUS_IRQCTRL 0x00b
58: #define GUS_REGISTERCTRL 0x00f
59:
60: // GUS Kommandos
61:
62: #define GUS_CMD_RESET 0x4c
63: #define GUS_CMD_DRAMDMACTRL 0x41
64: #define GUS_CMD_DMASTARTADR 0x42
65: #define GUS_CMD_DRAMIOADRLO 0x43
66: #define GUS_CMD_DRAMIOADRHI 0x44
67: #define GUS_CMD_TIMERCTRL 0x45
68: #define GUS_CMD_COUNTER1 0x46
69: #define GUS_CMD_COUNTER2 0x47
70: #define GUS_CMD_SAMPLEFREQ 0x48
71: #define GUS_CMD_SAMPLECTRL 0x49
72:
73: #define GUS_CMD_VOICECTRLW 0x00
74: #define GUS_CMD_FREQUCTRLW 0x01
75: #define GUS_CMD_STARTHIW 0x02
76: #define GUS_CMD_STARTLOW 0x03
77: #define GUS_CMD_ENDHIW 0x04
78: #define GUS_CMD_ENDLOW 0x05
79: #define GUS_CMD_RAMPRATEW 0x06
80: #define GUS_CMD_VOLUMEW 0x09
81: #define GUS_CMD_CURRENTHIW 0x0a
82: #define GUS_CMD_CURRENTLOW 0x0b
83: #define GUS_CMD_PANPOSW 0x0c
84: #define GUS_CMD_VOLUMECTRLW 0x0d
85: #define GUS_CMD_ACTIVEVOICESW 0x0e
86:
87: #define GUS_CMD_VOICECTRLR 0x80
88: #define GUS_CMD_FREQUCTRLR 0x81
89: #define GUS_CMD_STARTHIR 0x82
90: #define GUS_CMD_STARTLOR 0x83
91: #define GUS_CMD_ENDHIR 0x84
92: #define GUS_CMD_ENDLOR 0x85
93: #define GUS_CMD_VOLUMER 0x89
94: #define GUS_CMD_CURRENTHIR 0x8a
95: #define GUS_CMD_CURRENTLOR 0x8b
96: #define GUS_CMD_PANPOSR 0x8c
97: #define GUS_CMD_VOLUMECTRLR 0x8d
98: #define GUS_CMD_ACTIVEVOICESR 0x8e
99: #define GUS_CMD_IRQSOURCER 0x8f
100:
101: #define ADDR_HI(x) ((UWORD)((((ULONG)(x))>>7L)&0x1fffL))
102: #define ADDR_LO(x) ((UWORD)((((ULONG)(x))&0x7fL)<<9L))
103:
104:
105: #define LSW( x ) ((UWORD)(((ULONG)(x))&0xffffL))
106: #define MSW( x ) ((UWORD)(((ULONG)(x))>>16L))
107: #define LSB( x ) ((UBYTE)(((UWORD)(x))&0xffL))
108: #define MSB( x ) ((UBYTE)(((UWORD)(x))>>8))
109: #define CONVTO16B( x ) ((((x)>>1L)&0x0001ffffL)|((x)&0x000c0000L))
110: #define NUMPARAS(bytesize) (((bytesize)+15) >> 4)
111:
112:
113:
114: // Variablen
115:
116:
117: UWORD uwGUSPort;
118: UBYTE ubGUSGF1Int;
119: UBYTE ubGUSMIDIInt;
120: UBYTE ubGUSDMA1;
121: UBYTE ubGUSDMA2;
122: UBYTE ubGUSUsedBits; // 0 if 8 bit or 4 if 16 bit
123: UWORD uwGUSUsedFreq;
124: UBYTE ubGUSGF1IRQVector; // Physikalischer Vektor des GF1 IRQ's
125: UBYTE *pGUSBuffer; // Zwischenpuffer
126: ULONG nGUSBufferWriteIndex;
127: ULONG nGUSBufferReadIndex;
128: ULONG ulBytesInBuffer; // Anzahl der Bytes im Puffer
129: ULONG ulGUSSndBufSize;
130: ULONG ulDMABufMaxSize;
131:
132:
133: int bIgnoreGF1IRQ=TRUE;
134: int bDMAInProgress=FALSE;
135: int bWarnFlag=TRUE; // Flag, ob Warnungen ausgeben werden sollen
136: int nWarnCnt=0;
137: #define MAXWARNS 5 // Anzahl der maximalen Warnungen
138:
139: _go32_dpmi_seginfo old_pmintGF1; /* the old interrupt handler */
140: _go32_dpmi_seginfo pm_wrapperGF1; /* the new interrupt handler */
141:
142: UBYTE ubDummy;
143:
144:
145:
146:
147: static __inline__ void WriteGUSb( UWORD uwReg, UBYTE ubByte )
148: {
149: outportb( uwGUSPort+uwReg, ubByte );
150: }
151:
152: static __inline__ UBYTE ReadGUSb( UWORD uwReg )
153: {
154: return inportb( uwGUSPort+uwReg );
155: }
156:
157: static __inline__ void WriteGUSw( UWORD uwReg, UWORD uwWord )
158: {
159: outportw( uwGUSPort+uwReg, uwWord );
160: }
161:
162: static __inline__ UWORD ReadGUSw( UWORD uwReg )
163: {
164: return inportw( uwGUSPort+uwReg );
165: }
166:
167:
168:
169: _go32_dpmi_seginfo dma_mem; // Zeiger auf DMA-Speicher
170: ULONG dmabufadr;
171:
172: void GUS_GF1Delay( void )
173: {
174:
175: int i;
176:
177: for( i=0; i<6; i++ )
1.1.1.2 ! root 178: inportb( uwGUSPort+GUS_DATAHI );
1.1 root 179:
180:
181: }
182:
183: /*******************************
184:
185: void GUS_Reset( UBYTE ubGUSDMA1, UBYTE ubGUSDMA2, ubGUSGF1Int )
186:
187: *******************************/
188:
189: void GUS_Reset( UBYTE ubGUSDMA1, UBYTE ubGUSDMA2, UBYTE ubGUSGF1Int )
190: {
191: int i, j;
192: UBYTE nDMA, nInt;
193:
194: WriteGUSb( GUS_MIXER, 1|2 ); // Latches aus, Alle Aus/Eingaben aus
195:
196: // Reset
197: WriteGUSb( GUS_COMMAND, GUS_CMD_RESET );
198: WriteGUSb( GUS_DATAHI, 0 );
199: delay( 100 );
200: WriteGUSb( GUS_COMMAND, GUS_CMD_RESET );
201: WriteGUSb( GUS_DATAHI, 1 );
202: delay( 100 );
203:
204: // DMA Control Register reset
205: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
206: WriteGUSb( GUS_DATAHI, 0 );
207: delay( 10 );
208:
209: // Timer Control Register
210: WriteGUSb( GUS_COMMAND, GUS_CMD_TIMERCTRL );
211: WriteGUSb( GUS_DATAHI, 0 );
212: delay( 10 );
213:
214: // Sampling Control Register
215: WriteGUSb( GUS_COMMAND, GUS_CMD_SAMPLECTRL );
216: WriteGUSb( GUS_DATAHI, 0 );
217: delay( 10 );
218:
219: // Number of Voices
220: WriteGUSb( GUS_COMMAND, GUS_CMD_ACTIVEVOICESW );
221: WriteGUSb( GUS_DATAHI, 0xc0 | (15-1) ); // 15 Voices (left/right)
222:
223: // Evtl. anstehende DMA-IRQ's holen
224: ReadGUSb( GUS_IRQSTATE );
225: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
226: ReadGUSb( GUS_DATAHI );
227:
228: // Evtl. Sampleinterrupts lesen
229: WriteGUSb( GUS_COMMAND, GUS_CMD_SAMPLECTRL );
230: ReadGUSb( GUS_DATAHI );
231:
232: // IRQ-Status lesen
233: WriteGUSb( GUS_COMMAND, GUS_CMD_IRQSOURCER );
234: ReadGUSb( GUS_DATAHI );
235:
236: // Alle Stimmen abschalten
237:
238: for( i=0; i<32; i++ )
239: {
1.1.1.2 ! root 240: WriteGUSb( GUS_VOICE, (UBYTE)i );
! 241: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
! 242: WriteGUSb( GUS_DATAHI, 3 ); // Stimme stoppen
! 243: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 244: WriteGUSb( GUS_DATAHI, 3 ); // Lautstaerke 0
! 245: WriteGUSb( GUS_COMMAND, GUS_CMD_RAMPRATEW );
! 246: WriteGUSb( GUS_DATAHI, 0 ); // Ramp 0
1.1 root 247:
248: }
249:
250: // Evtl. anstehende DMA-IRQ's holen
251: ReadGUSb( GUS_IRQSTATE );
252: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
253: ReadGUSb( GUS_DATAHI );
254:
255: // Evtl. Sampleinterrupts lesen
256: WriteGUSb( GUS_COMMAND, GUS_CMD_SAMPLECTRL );
257: ReadGUSb( GUS_DATAHI );
258:
259: // IRQ-Status lesen
260: WriteGUSb( GUS_COMMAND, GUS_CMD_IRQSOURCER );
261: ReadGUSb( GUS_DATAHI );
262:
263:
264: // Reset beenden und GF1 Master IRQ einschalten
265: WriteGUSb( GUS_COMMAND, GUS_CMD_RESET );
266: WriteGUSb( GUS_DATAHI, 7 );
267:
268:
269: if( ubGUSDMA1 == 0 ) // IRQ's und DMA einstellen ?
1.1.1.2 ! root 270: return; // Nein, dann Ende
1.1 root 271:
272:
273: // Digital ASIC einstellen
274:
275: WriteGUSb( GUS_REGISTERCTRL, 5 ); // IRQ's-Register waehlen
276: WriteGUSb( GUS_MIXER, 1|2 ); // Alles Abschalten
277: WriteGUSb( GUS_IRQCTRL, 0 ); // IRQ's loeschen
278: WriteGUSb( GUS_REGISTERCTRL, 0 ); // Alte Registerkonfig wieder einschalten
279:
280: // DMA selektieren
281:
282: nDMA=0;
283: for( j=0; j<2; j++ )
284: {
1.1.1.2 ! root 285: switch( ((j!=0)?(ubGUSDMA1):(ubGUSDMA2)) )
! 286: {
! 287: case 1:
! 288: nDMA |= 1;
! 289: break;
! 290: case 3:
! 291: nDMA |= 2;
! 292: break;
! 293: case 5:
! 294: nDMA |= 3;
! 295: break;
! 296: case 6:
! 297: nDMA |= 4;
! 298: break;
! 299: case 7:
! 300: nDMA |= 5;
! 301: break;
! 302: }
! 303: if( j==0 )
! 304: nDMA=nDMA<<3;
1.1 root 305: }
306:
307: if( ubGUSDMA1 == ubGUSDMA2 ) // Gleichen DMA fuer beides ?
1.1.1.2 ! root 308: nDMA = (nDMA&0x3)|(1<<6);
1.1 root 309:
310:
311: // Interrupt der GUS setzen
312:
313: nInt=0;
314: for( j=0; j<2; j++ )
315: {
1.1.1.2 ! root 316: switch( (j!=0)?(ubGUSGF1Int):(ubGUSMIDIInt) )
! 317: {
! 318: case 2:
! 319: nInt |= 1;
! 320: break;
! 321: case 5:
! 322: nInt |= 2;
! 323: break;
! 324: case 3:
! 325: nInt |= 3;
! 326: break;
! 327: case 7:
! 328: nInt |= 4;
! 329: break;
! 330: case 11:
! 331: nInt |= 5;
! 332: break;
! 333: case 12:
! 334: nInt |= 6;
! 335: break;
! 336: case 15:
! 337: nInt |= 7;
! 338: break;
! 339: }
! 340: if( j==0 )
! 341: nInt=nInt<<3;
1.1 root 342: }
343:
344: if( ubGUSGF1Int == ubGUSMIDIInt )
1.1.1.2 ! root 345: nInt = (nInt&0x3)|(1<<6);
1.1 root 346:
347:
348:
349: disable();
350:
351: WriteGUSb( GUS_MIXER, 1|2 ); // DMA-Einstellung aktivieren
352: WriteGUSb( GUS_DMACTRL, nDMA | 0x80 ); // DMA-Kanal selektieren, welcher im SET angegebe wurde
353:
354:
355: WriteGUSb( GUS_MIXER, 1|2|64 ); // IRQ's selektieren
356: WriteGUSb( GUS_IRQCTRL, nInt );
357:
358: WriteGUSb( GUS_MIXER, 1|2 ); // DMA-Einstellung aktivieren
359: WriteGUSb( GUS_DMACTRL, nDMA ); // DMA-Kanal selektieren, welcher im SET angegebe wurde
360:
361: WriteGUSb( GUS_MIXER, 1|2|64 ); // IRQ's selektieren
362: WriteGUSb( GUS_IRQCTRL, nInt );
363:
364: enable();
365:
366: // IRQ/DMA locken
367:
368: WriteGUSb( GUS_VOICE, 0 );
369:
370: WriteGUSb( GUS_MIXER, 8 | ((ubGUSGF1Int==ubGUSMIDIInt)?16:0 ) );
371:
372: WriteGUSb( GUS_VOICE, 0 );
373:
374:
375:
376: }
377:
378:
379:
380: /*******************************
381:
382: int GUS_Init( void )
383:
384: *******************************/
385:
386: int GUS_Init( int *dspbits, int *rate, int *sndbufsize, unsigned int *direct_buffers, int *stereo_sound )
387: {
388:
389: char *szGUSENVStr, *pz;
390: int i, j;
391: extern void (*SND_Write)(void *buf, unsigned long size);
392:
393:
394:
395: szGUSENVStr = getenv( "ULTRASND" );
396: if( szGUSENVStr == 0 )
1.1.1.2 ! root 397: return 0;
1.1 root 398:
399:
400: if( (*dspbits != 8 ) && (*dspbits != 16 ) )
401: {
1.1.1.2 ! root 402: printf( "%d bits are not supported on the GUS !\n", dspbits );
! 403: return 0;
1.1 root 404: }
405:
406:
407: ubGUSUsedBits = (*dspbits==8)?0:4;
408:
409: if( (*rate < 1000) || (*rate > 44100 ))
410: {
1.1.1.2 ! root 411: fprintf( stderr, "%dHz are not supported on the GUS !\n", *rate );
! 412: return 0;
1.1 root 413: }
414:
415: uwGUSUsedFreq = *rate;
416:
417:
418:
419: ulDMABufMaxSize = 8192;
420: ulGUSSndBufSize = ((ULONG)*sndbufsize)*32;
421:
422:
423:
424: fprintf( stderr, "GUS configured for %d bits, %d Hz\n", *dspbits, *rate );
425: fprintf( stderr, "Soundbuffersize: %d bytes\n", ulGUSSndBufSize );
426: fprintf( stderr, "DMA-buffersize: %d bytes\n", ulDMABufMaxSize );
427: fprintf( stderr, "Fragmentsize: %d bytes\n", *sndbufsize );
428:
429:
430: uwGUSPort = (UWORD)strtol( szGUSENVStr, (char **)NULL, 16 );
431: pz = strchr( szGUSENVStr, ',' );
432: if( (pz == 0) || (uwGUSPort ==0) )
1.1.1.2 ! root 433: return 0;
1.1 root 434:
435: ubGUSDMA1 = (UBYTE)atol( pz+1 );
436: pz = strchr( pz+1, ',' );
437: if( pz == 0 )
1.1.1.2 ! root 438: return 0;
1.1 root 439:
440: ubGUSDMA2 = (UBYTE)atol( pz+1 );
441:
442: pz = strchr( pz+1, ',' );
443: if( pz == 0 )
1.1.1.2 ! root 444: return 0;
1.1 root 445:
446: ubGUSGF1Int = (UBYTE)atol( pz+1 );
447: if( ubGUSGF1Int == 0 )
1.1.1.2 ! root 448: return 0;
1.1 root 449:
450: pz = strchr( pz+1, ',' );
451: if( pz == 0 )
1.1.1.2 ! root 452: return 0;
1.1 root 453:
454: ubGUSMIDIInt = (UBYTE)atol( pz+1 );
455: if( ubGUSMIDIInt == 0 )
1.1.1.2 ! root 456: return 0;
1.1 root 457:
458: // Speicher fuer DMA holen
459:
460:
461: memset( &dma_mem, 0, sizeof( _go32_dpmi_seginfo ) );
462: dma_mem.size = NUMPARAS( ulDMABufMaxSize+1000 );
463: dmabufadr = DMA_AllocDMABuf( &dma_mem );
464:
465:
466: _go32_dpmi_lock_code( GUS_PlayBuffer, (ULONG)GUS_DummyFunc - (ULONG)GUS_PlayBuffer);
467: _go32_dpmi_lock_data( &uwGUSPort, (ULONG)&ubDummy - (ULONG)&uwGUSPort);
468:
469:
470: if( dmabufadr == NULL)
471: {
472: fprintf( stderr, "Cannot allocate DOS memory for DMA buffers!\n" );
473: return 0;
474: }
475:
476:
477: // Zwischenpuffer allokieren
478:
479: pGUSBuffer = (UBYTE *)malloc( ulGUSSndBufSize+1000 );
480: if( pGUSBuffer == 0 )
481: {
1.1.1.2 ! root 482: fprintf( stderr, "Cannot allocate soundbuffer !\n" );
! 483: return 0;
1.1 root 484: }
485:
486: nGUSBufferWriteIndex = nGUSBufferReadIndex = 0;
487: ulBytesInBuffer = 0;
488:
489: // GUS-Reset
490:
491: GUS_Reset( ubGUSDMA1, ubGUSDMA2, ubGUSGF1Int );
492:
493:
494: // Test, ob wir in das GUS-RAM etwas schreiben koennen
495:
496: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRLO );
497: WriteGUSw( GUS_DATALO, 0 );
498: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRHI );
499: WriteGUSw( GUS_DATAHI, 0 );
500:
501: WriteGUSb( GUS_DRAM, 0x15 );
502: delay( 100 );
503: if( ReadGUSb( GUS_DRAM ) != 0x15 ) // Bytes unterschiedlich ?
1.1.1.2 ! root 504: return 0;
1.1 root 505:
506: // GUS-RAM loeschen
507:
508: j=-1;
509: for( i=0; i<(int)(ulDMABufMaxSize*2+1000); i++ )
510: {
1.1.1.2 ! root 511: if( j != MSW(i) ) // Muss das Highword veraendert werden ?
! 512: {
! 513: j = MSW(i);
! 514:
! 515: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRHI );
! 516: WriteGUSw( GUS_DATALO, MSW( i ) );
! 517: }
1.1 root 518:
1.1.1.2 ! root 519: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRLO );
! 520: WriteGUSw( GUS_DATALO, LSW( i ) );
1.1 root 521:
1.1.1.2 ! root 522: WriteGUSb( GUS_DRAM, 0 );
1.1 root 523:
524: }
525:
526:
527: // Interrupthandler installieren
528:
529: memset( &pm_wrapperGF1, 0, sizeof( _go32_dpmi_seginfo ) );
530: pm_wrapperGF1.pm_offset = (int) GUS_GF1InterruptHandler;
531: if(_go32_dpmi_allocate_iret_wrapper( &pm_wrapperGF1 ) )
532: {
1.1.1.2 ! root 533: fprintf( stderr, "Cannot allocate protected mode wrapper for GUS interrupt!\n");
! 534: if( dmabufadr != 0 )
! 535: _go32_dpmi_free_dos_memory( &dma_mem );
1.1 root 536:
1.1.1.2 ! root 537: return 0;
1.1 root 538: }
539:
540:
541: ubGUSGF1IRQVector = (ubGUSGF1Int>7)?(ubGUSGF1Int+0x68):(ubGUSGF1Int+0x08); // Physik. Vektor berechnen
542:
543: _go32_dpmi_get_protected_mode_interrupt_vector( ubGUSGF1IRQVector, &old_pmintGF1 ); // Alten Interrupt merken
544: _go32_dpmi_set_protected_mode_interrupt_vector( ubGUSGF1IRQVector, &pm_wrapperGF1 ); // Neuen Interrupt merken
545:
546:
547: // Interrupt erlauben
548:
549: if( ubGUSGF1Int > 7 )
550: {
1.1.1.2 ! root 551: outportb( 0xA1, inportb( 0xA1 ) & ~(1 << ( ubGUSGF1Int-8 ) ) );
! 552: outportb( 0xA0, 0x20 );
1.1 root 553: }
554: else
555: {
1.1.1.2 ! root 556: outportb( 0x21, inportb( 0x21 ) & ~(1 << ubGUSGF1Int));
! 557: outportb( 0x20, 0x20 );
1.1 root 558: }
559:
560:
561: // Hier wird die Stimme zum erstenmal gestertet
562:
563:
564: WriteGUSb( GUS_VOICE, 0 ); // Stimme0
565:
566: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMEW ); // Lautstaerke auf Maximum
567: WriteGUSw( GUS_DATALO, 61247 );
568:
569: WriteGUSb( GUS_COMMAND, GUS_CMD_FREQUCTRLW ); // 15 Stimmen = x / 40!
570:
571: // WriteGUSw( GUS_DATALO, (UWORD)((((((((ULONG)uwGUSUsedFreq)/1000L)<<9L)+(44100L>>1L))/44100L)<<1L)) );
572: WriteGUSw( GUS_DATALO, uwGUSUsedFreq/40 );
573:
574:
575: WriteGUSb( GUS_COMMAND, GUS_CMD_CURRENTLOW ); // Current
576: WriteGUSw( GUS_DATALO, 32 );
577: WriteGUSb( GUS_COMMAND, GUS_CMD_CURRENTHIW );
578: WriteGUSw( GUS_DATALO, 0 );
579:
580: WriteGUSb( GUS_COMMAND, GUS_CMD_STARTHIW ); // Start
581: WriteGUSw( GUS_DATALO, 0 );
582: WriteGUSb( GUS_COMMAND, GUS_CMD_STARTLOW );
583: WriteGUSw( GUS_DATALO, 32 );
584:
585: if( ubGUSUsedBits == 0 ) // 8 oder 16 Bit ?
586: {
1.1.1.2 ! root 587: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende setzen
! 588: WriteGUSw( GUS_DATALO, ADDR_HI( ulDMABufMaxSize+32 ) );
! 589: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 590: WriteGUSw( GUS_DATALO, ADDR_LO( ulDMABufMaxSize+32 ) );
1.1 root 591: }
592: else
593: {
1.1.1.2 ! root 594: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende
! 595: WriteGUSw( GUS_DATALO, ADDR_HI( CONVTO16B( ulDMABufMaxSize+32 ) ) );
! 596: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 597: WriteGUSw( GUS_DATALO, ADDR_LO( CONVTO16B( ulDMABufMaxSize+32 ) ) );
1.1 root 598: }
599:
600: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
601: WriteGUSb( GUS_DATAHI, 3|4 );
602: GUS_GF1Delay();
603: WriteGUSb( GUS_DATAHI, 3|4 ); // Rollover an
604:
605:
606: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
607: WriteGUSb( GUS_DATAHI, 32|ubGUSUsedBits );
608: GUS_GF1Delay();
609: WriteGUSb( GUS_DATAHI, 32|ubGUSUsedBits ); // Stimme starten, Loop aus
610:
611:
612: bIgnoreGF1IRQ = FALSE;
613:
614:
615: // GUS-Initialisierung beendet, puhhh
616:
617: fprintf( stderr, "GUS found at port: %Xh, dma1: %d, dma2: %d, GF1-int: %d, MIDI-int: %d\n", uwGUSPort, ubGUSDMA1, ubGUSDMA2, ubGUSGF1Int, ubGUSMIDIInt );
618:
619:
620: atexit( GUS_Cleanup );
621:
622:
623: SND_Write = GUS_PlayBuffer; // Zeiger auf meine Abspielroutine eintragen
624: direct_buffers[0] = 0; // Direct access not supported
625: direct_buffers[1] = 0;
626: *stereo_sound = 0;
627:
628:
629: printf( "First ....(%ld,%X)\n", ulBytesInBuffer, &ulBytesInBuffer );
630:
631:
632: return 1;
633:
634: }
635:
636:
637: /*******************************
638:
639: int GUS_Cleanup( void )
640:
641: *******************************/
642:
643:
644: void GUS_Cleanup( void )
645: {
646:
647:
648: fprintf( stderr, "Freeing up all GUS-stuff\n" );
649:
650: // Warten, bis DMA beendet ist
651:
652: if( bDMAInProgress == TRUE )
653: {
1.1.1.2 ! root 654: do
! 655: {
! 656: delay( 10 );
! 657: }
! 658: while( bDMAInProgress == TRUE );
1.1 root 659: }
660:
661:
662: // Stimmen anhalten
663:
664: WriteGUSb( GUS_VOICE, 0 );
665:
666: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
667: WriteGUSb( GUS_DATAHI, 3 );
668: GUS_GF1Delay();
669: WriteGUSb( GUS_DATAHI, 3 );
670:
671:
672: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
673: WriteGUSb( GUS_DATAHI, 3 );
674: GUS_GF1Delay();
675: WriteGUSb( GUS_DATAHI, 3 );
676:
677: // GUS resetten
678:
679: GUS_Reset( 0, 0, 0 );
680:
681: // Interrupts wieder sperren
682:
683: if( ubGUSGF1Int > 7 )
1.1.1.2 ! root 684: outportb (0xA1, inportb(0xA1) | (1 << (ubGUSGF1Int-8)));
1.1 root 685: else
1.1.1.2 ! root 686: outportb (0x21, inportb(0x21) | (1 << ubGUSGF1Int));
1.1 root 687:
688: _go32_dpmi_set_protected_mode_interrupt_vector( ubGUSGF1IRQVector, &old_pmintGF1 );
689: _go32_dpmi_free_iret_wrapper( &pm_wrapperGF1 );
690:
691:
692: // Speicher freigeben
693:
694: if( pGUSBuffer != 0 )
1.1.1.2 ! root 695: free( pGUSBuffer );
1.1 root 696:
697: if( dmabufadr != 0 )
1.1.1.2 ! root 698: _go32_dpmi_free_dos_memory( &dma_mem ); // Speicher fuer DMA freigeben
1.1 root 699:
700: GUS_Reset( 0, 0, 0 );
701:
702: }
703:
704: /*******************************
705:
706: void GUS_PlayBuffer( void *buf, unsigned long size )
707:
708: *******************************/
709:
710:
711: // Diese Routine wird vom UAE aufgerufen, wenn der Soundbuffer
712: // zu leeren ist
713:
714:
715: void GUS_PlayBuffer( void *buf, unsigned long size )
716: {
717: ULONG i, j;
718:
719:
720: j=0;
721: while( ulBytesInBuffer>ulDMABufMaxSize*2 );
722: /*
723: {
1.1.1.2 ! root 724: fprintf( stderr, "Waiting ....(%ld,%X)\n", ulBytesInBuffer, &ulBytesInBuffer );
! 725: fflush( stderr );
! 726: j++;
! 727: if( j>50 )
! 728: {
! 729: fprintf( stderr, "Breche ab ...\n" );
! 730: fflush( stderr );
! 731: break;
! 732: }
1.1 root 733:
734: } */
735:
736: disable();
737:
738: // Daten in den GUS-Buffer kopieren
739:
740: if( size+ulBytesInBuffer>ulGUSSndBufSize )
741: {
1.1.1.2 ! root 742: if( bWarnFlag == TRUE )
! 743: {
! 744: fprintf( stderr, "Error: GUS-soundbuffer overflow !\n" );
! 745: nWarnCnt++;
! 746: if( nWarnCnt>MAXWARNS )
! 747: {
! 748: bWarnFlag = FALSE;
! 749: fprintf( stderr, "GUS: No further messages !\n" );
! 750: }
! 751: }
1.1 root 752:
753: }
754: else
755: {
1.1.1.2 ! root 756: // GUS-Buffer fuellen
1.1 root 757:
1.1.1.2 ! root 758: // Koennen wir auf einmal kopieren ?
1.1 root 759:
1.1.1.2 ! root 760: i = ulGUSSndBufSize-nGUSBufferWriteIndex;
! 761: if( i < size )
! 762: {
! 763: memcpy( pGUSBuffer+nGUSBufferWriteIndex, buf, i );
1.1 root 764:
1.1.1.2 ! root 765: memcpy( pGUSBuffer, ((UBYTE*)buf)+i, size-i );
1.1 root 766:
1.1.1.2 ! root 767: }
! 768: else
! 769: {
! 770: memcpy( pGUSBuffer+nGUSBufferWriteIndex, buf, size );
! 771: }
1.1 root 772:
1.1.1.2 ! root 773: nGUSBufferWriteIndex = (nGUSBufferWriteIndex+size)&(ulGUSSndBufSize-1);
1.1 root 774:
1.1.1.2 ! root 775: ulBytesInBuffer += size;
1.1 root 776:
777: }
778:
779: enable();
780:
781: }
782:
783:
784: /*******************************
785:
786: void GUS_StartDMA( ULONG ulPosInGUSRAM )
787:
788: *******************************/
789:
790:
791:
792: void GUS_StartDMA( ULONG ulPosInGUSRAM, int bLoop )
793: {
794:
795: ULONG i, pDMABuf, j;
796: ULONG ulTemp;
797:
798:
799: // I hope, everything is aligned to 4 byte (32bit), otherwise
800: // the machine my crash :(
801:
802:
803: if( bDMAInProgress == TRUE )
804: {
1.1.1.2 ! root 805: fprintf( stderr, "Error in StartDMA, DMA already im progress !\n" );
! 806: return;
1.1 root 807: }
808:
809: bDMAInProgress=TRUE;
810:
811: // Kopiert die Daten aus dem Soundbuffer in den DMA-Puffer
812:
813:
814: _farsetsel( _dos_ds );
815:
816: if( ulBytesInBuffer == 0 ) // Sind ueberhaupt Daten im Puffer ?
817: { // Nein, dann DMA-Buffer loeschen
1.1.1.2 ! root 818: pDMABuf = dmabufadr;
1.1 root 819:
1.1.1.2 ! root 820: if( ubGUSUsedBits == 0 ) // 8 Bit ?
! 821: ulTemp = 0x80808080UL;
! 822: else
! 823: ulTemp = 0;
! 824:
! 825: for( i=ulDMABufMaxSize/4; i>0; i-- )
! 826: {
! 827: _farnspokel( pDMABuf, ulTemp );
! 828: pDMABuf+=4;
! 829: }
1.1 root 830:
831: }
832: else
833: {
1.1.1.2 ! root 834: if( ulBytesInBuffer >= ulDMABufMaxSize ) // Sind mehr Daten da, als
! 835: { // der Puffer gross ist ?
1.1 root 836:
1.1.1.2 ! root 837: pDMABuf = dmabufadr; // Ja, DMA-Puffer vollmachen
1.1 root 838:
1.1.1.2 ! root 839: j = nGUSBufferReadIndex;
! 840: for( i=ulDMABufMaxSize/4; i>0; i-- )
! 841: {
! 842: _farnspokel( pDMABuf, *((ULONG*)(pGUSBuffer+j)) ); // 32 bit-copy
! 843: pDMABuf+=4;
! 844: j = (j+4)&(ulGUSSndBufSize-1);
! 845: }
! 846:
! 847: nGUSBufferReadIndex = (nGUSBufferReadIndex+ulDMABufMaxSize)&(ulGUSSndBufSize-1);
! 848:
! 849: ulBytesInBuffer -= ulDMABufMaxSize;
! 850: }
! 851: else
! 852: {
! 853: pDMABuf = dmabufadr; // Nein, nur den vorhanden Teil
! 854: // kopieren
! 855:
! 856: j = nGUSBufferReadIndex;
! 857: for( i=ulBytesInBuffer/4; i>0; i-- )
! 858: {
! 859: _farnspokel( pDMABuf, *((ULONG*)(pGUSBuffer+j)) );
! 860: pDMABuf+=4;
! 861: j = (j+4)&(ulGUSSndBufSize-1);
! 862: }
! 863: nGUSBufferReadIndex = (nGUSBufferReadIndex+ulBytesInBuffer)&(ulGUSSndBufSize-1);
! 864:
! 865:
! 866: if( ubGUSUsedBits == 0 ) // 8 Bit ?
! 867: ulTemp = 0x80808080UL;
! 868: else
! 869: ulTemp = 0;
! 870:
! 871:
! 872: for( i=(ulDMABufMaxSize-ulBytesInBuffer)/4; i>0; i-- )
! 873: {
! 874: _farnspokel( pDMABuf, ulTemp );
! 875: pDMABuf+=4;
! 876: }
1.1 root 877:
878:
1.1.1.2 ! root 879: ulBytesInBuffer = 0;
! 880: }
1.1 root 881:
882: }
883:
884:
885: if( bLoop == TRUE ) // Byte/Word kopieren, um das Geklicke zu verhindern
886: {
887:
1.1.1.2 ! root 888: if( ubGUSUsedBits == 0 ) // 8 Bit ?
! 889: {
1.1 root 890:
1.1.1.2 ! root 891: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRHI );
! 892: WriteGUSw( GUS_DATALO, MSW( ulPosInGUSRAM-ulDMABufMaxSize-1 ) );
1.1 root 893:
1.1.1.2 ! root 894: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRLO );
! 895: WriteGUSw( GUS_DATALO, LSW( ulPosInGUSRAM-ulDMABufMaxSize-1 ) );
1.1 root 896:
1.1.1.2 ! root 897: WriteGUSb( GUS_DRAM, _farnspeekb( dmabufadr+ulDMABufMaxSize-1 )+0x80 );
1.1 root 898:
1.1.1.2 ! root 899: }
! 900: else
! 901: {
! 902: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRHI );
! 903: WriteGUSw( GUS_DATALO, MSW( ulPosInGUSRAM-ulDMABufMaxSize-2 ) );
1.1 root 904:
1.1.1.2 ! root 905: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRLO );
! 906: WriteGUSw( GUS_DATALO, LSW( ulPosInGUSRAM-ulDMABufMaxSize-2 ) );
1.1 root 907:
1.1.1.2 ! root 908: WriteGUSb( GUS_DRAM, _farnspeekb( dmabufadr+ulDMABufMaxSize-2 ) );
1.1 root 909:
1.1.1.2 ! root 910: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRHI );
! 911: WriteGUSw( GUS_DATALO, MSW( ulPosInGUSRAM-ulDMABufMaxSize-1 ) );
1.1 root 912:
1.1.1.2 ! root 913: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMIOADRLO );
! 914: WriteGUSw( GUS_DATALO, LSW( ulPosInGUSRAM-ulDMABufMaxSize-1 ) );
1.1 root 915:
1.1.1.2 ! root 916: WriteGUSb( GUS_DRAM, _farnspeekb( dmabufadr+ulDMABufMaxSize-1 ) );
1.1 root 917:
1.1.1.2 ! root 918: }
1.1 root 919:
920: }
921:
922:
923: // DMA-Controller initialisieren
924: DMA_InitTransfer( ubGUSDMA1, DMA_READ, dmabufadr, ulDMABufMaxSize );
925:
926: // GUS-Register initialisieren
927: WriteGUSb( GUS_COMMAND, GUS_CMD_DMASTARTADR );
928: if( ubGUSDMA1>3 )
1.1.1.2 ! root 929: WriteGUSw( GUS_DATALO, CONVTO16B(ulPosInGUSRAM>>4) ); // Adresse>>4 !!!!
1.1 root 930: else
1.1.1.2 ! root 931: WriteGUSw( GUS_DATALO, (UWORD)(ulPosInGUSRAM>>4) ); // Adresse>>4 !!!!
1.1 root 932:
933: if( ubGUSUsedBits == 0 )
934: { // 8 Bit
1.1.1.2 ! root 935: if( ubGUSDMA1>3 )
! 936: {
! 937: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
! 938: WriteGUSb( GUS_DATAHI, 0x85 | 0x20 ); // Mit signed->unsigned kopieren
! 939:
! 940: }
! 941: else
! 942: {
! 943: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
! 944: WriteGUSb( GUS_DATAHI, 0x81 | 0x20 );
! 945: }
1.1 root 946: }
947: else
948: { // 16 Bit
1.1.1.2 ! root 949: if( ubGUSDMA1>3 )
! 950: {
! 951: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
! 952: WriteGUSb( GUS_DATAHI, 0x05 | 0x20 ); // Ohne signed->unsigned kopieren
! 953:
! 954: }
! 955: else
! 956: {
! 957: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
! 958: WriteGUSb( GUS_DATAHI, 0x01 | 0x20 );
! 959: }
1.1 root 960:
961:
962: }
963:
964: }
965:
966:
967:
968: /*******************************
969:
970: void GUS_WorkOnVoices( void )
971:
972: *******************************/
973:
974:
975: // Hier werden die Interrupts der einzelnen Stimmen bearbeitet
976:
977: void GUS_WorkOnVoices( void )
978: {
979:
980: UBYTE ubIntArt, ubTemp1, ubTemp2;
981: int i, nVoice, nVoiceBit, nWaveIgnore=0, nVolumeIgnore=0;
982: int nIntCounts=0;
983:
984: // Alle anstehenden Interrupts bearbeiten
985:
986: for(;;)
987: {
988:
989:
1.1.1.2 ! root 990: WriteGUSb( GUS_COMMAND, GUS_CMD_IRQSOURCER ); // IRQ-Art holen
! 991: ubIntArt = ReadGUSb( GUS_DATAHI );
1.1 root 992:
1.1.1.2 ! root 993: nVoice = ubIntArt & 0x1f;
! 994: nVoiceBit = ((ULONG)1)<<((ULONG)nVoice);
1.1 root 995:
1.1.1.2 ! root 996: // Alle Interrupts abgearbeitet ?
! 997: if( ( ubIntArt & 192) == 192 ) // Negative Logik !!!!
! 998: {
! 999: break;
! 1000: }
! 1001:
! 1002: nIntCounts++;
! 1003:
! 1004: if( nIntCounts>3 )
! 1005: {
! 1006: #ifdef DEBUG
! 1007: fprintf( stderr, "!!!! Breche Int. ab, da mehr als 3 Anfragen !!!\n" );
! 1008: #endif
! 1009:
! 1010: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 1011: WriteGUSb( GUS_DATAHI, 3 );
! 1012: GUS_GF1Delay();
! 1013: WriteGUSb( GUS_DATAHI, 3 );
! 1014:
! 1015: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
! 1016: WriteGUSb( GUS_DATAHI, 3 );
! 1017: GUS_GF1Delay();
! 1018: WriteGUSb( GUS_DATAHI, 3 );
! 1019:
! 1020: return;
! 1021: }
! 1022:
! 1023: if( bIgnoreGF1IRQ == TRUE )
! 1024: {
! 1025: #ifdef DEBUG
! 1026: fprintf( stderr, "\t\tIgnoriere IRQ !\n" );
! 1027: #endif
! 1028:
! 1029: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
! 1030: WriteGUSb( GUS_DATAHI, 3 ); // Loop aus, IRQ aus
! 1031:
! 1032: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 1033: WriteGUSb( GUS_DATAHI, 3 ); // Rollover an, IRQ an
! 1034: }
! 1035:
! 1036: #ifdef DEBUG
! 1037: fprintf( stderr, "\tBearbeite Stimme %d, IntArt: $%X\n", nVoice, ubIntArt );
! 1038: #endif
! 1039:
! 1040: if( ! (ubIntArt & 128 ) ) // WAVE-Table-IRQ ?
! 1041: {
! 1042: if( !(nWaveIgnore & nVoiceBit ))
! 1043: {
! 1044: nWaveIgnore |= nVoiceBit;
! 1045:
! 1046: #ifdef DEBUG
! 1047: fprintf( stderr,"\t\tBearbeite WAVE-IRQ\n" );
! 1048: #endif
! 1049:
! 1050: WriteGUSb( GUS_VOICE, nVoice );
! 1051: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLR );
! 1052: ubTemp1 = ReadGUSb( GUS_DATAHI );
! 1053:
! 1054: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLR );
! 1055: ubTemp2 = ReadGUSb( GUS_DATAHI );
! 1056:
! 1057:
! 1058: if( ubTemp2&4 ) // Ist das Rollover an ?
! 1059: { // Ja
! 1060:
! 1061: // Das Ende neu setzen
! 1062:
! 1063: if( ubGUSUsedBits == 0 ) // 8 Bit ?
! 1064: {
! 1065: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende setzen
! 1066: WriteGUSw( GUS_DATALO, ADDR_HI( ulDMABufMaxSize*2+32 ) );
! 1067: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 1068: WriteGUSw( GUS_DATALO, ADDR_LO( ulDMABufMaxSize*2+32 ) );
! 1069: }
! 1070: else
! 1071: {
! 1072: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende setzen
! 1073: WriteGUSw( GUS_DATALO, ADDR_HI( CONVTO16B( ulDMABufMaxSize*2+32 ) ) );
! 1074: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 1075: WriteGUSw( GUS_DATALO, ADDR_LO( CONVTO16B( ulDMABufMaxSize*2+32 ) ) );
! 1076: }
! 1077:
! 1078: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 1079: WriteGUSb( GUS_DATAHI, 3 );
! 1080: GUS_GF1Delay();
! 1081: WriteGUSb( GUS_DATAHI, 3 ); // Rollover aus
! 1082:
! 1083: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
! 1084: WriteGUSb( GUS_DATAHI, 32|8|ubGUSUsedBits );
! 1085: GUS_GF1Delay();
! 1086: WriteGUSb( GUS_DATAHI, 32|8|ubGUSUsedBits ); // Loop an
! 1087:
! 1088: GUS_StartDMA( 32, FALSE );
! 1089:
! 1090: }
! 1091: else
! 1092: {
! 1093:
! 1094: // Das Ende neu setzen
! 1095:
! 1096: if( ubGUSUsedBits == 0 )
! 1097: {
! 1098: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende setzen
! 1099: WriteGUSw( GUS_DATALO, ADDR_HI( ulDMABufMaxSize+32 ) );
! 1100: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 1101: WriteGUSw( GUS_DATALO, ADDR_LO( ulDMABufMaxSize+32 ) );
! 1102: }
! 1103: else
! 1104: {
! 1105: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDHIW ); // Ende setzen
! 1106: WriteGUSw( GUS_DATALO, ADDR_HI( CONVTO16B( ulDMABufMaxSize+32 ) ) );
! 1107: WriteGUSb( GUS_COMMAND, GUS_CMD_ENDLOW );
! 1108: WriteGUSw( GUS_DATALO, ADDR_LO( CONVTO16B( ulDMABufMaxSize+32 ) ) );
! 1109: }
! 1110:
! 1111: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 1112: WriteGUSb( GUS_DATAHI, 3|4 );
! 1113: GUS_GF1Delay();
! 1114: WriteGUSb( GUS_DATAHI, 3|4 ); // Rollover an
! 1115:
! 1116: WriteGUSb( GUS_COMMAND, GUS_CMD_VOICECTRLW );
! 1117: WriteGUSb( GUS_DATAHI, 32|ubGUSUsedBits );
! 1118: GUS_GF1Delay();
! 1119: WriteGUSb( GUS_DATAHI, 32|ubGUSUsedBits ); // Loop aus
! 1120:
! 1121: GUS_StartDMA( ulDMABufMaxSize+32, TRUE );
! 1122:
! 1123: }
! 1124:
! 1125: }
! 1126: }
! 1127:
! 1128: if( ! (ubIntArt & 64 ) ) // Volume-IRQ
! 1129: {
! 1130:
! 1131: if( !(nVolumeIgnore & nVoiceBit ))
! 1132: {
! 1133: nVolumeIgnore |= nVoiceBit;
! 1134: #ifdef DEBUG
! 1135: fprintf( stderr, "\t\tBearbeite Volume-IRQ\n" );
! 1136: #endif
! 1137:
! 1138: WriteGUSb( GUS_VOICE, nVoice );
! 1139: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLR );
! 1140: ubTemp2 = ReadGUSb( GUS_DATAHI );
! 1141:
! 1142: WriteGUSb(GUS_COMMAND, GUS_CMD_VOICECTRLR );
! 1143: ubTemp1 = ReadGUSb( GUS_DATAHI );
1.1 root 1144:
1145:
1.1.1.2 ! root 1146: WriteGUSb( GUS_COMMAND, GUS_CMD_VOLUMECTRLW );
! 1147: WriteGUSb( GUS_DATAHI, (ubTemp2 & (~32)) | 3 );
1.1 root 1148:
1.1.1.2 ! root 1149: }
1.1 root 1150:
1.1.1.2 ! root 1151: }
1.1 root 1152:
1153: }
1154: }
1155:
1156:
1157:
1158: /*******************************
1159:
1160: void GUS_GF1InterruptHandler( void )
1161:
1162: *******************************/
1163:
1164:
1165: // Hier werden alle Interrupts verarbeitet
1166:
1167: void GUS_GF1InterruptHandler( void )
1168: {
1169:
1170: UBYTE ubIntArt, ubTemp;
1171:
1172:
1173:
1174:
1175: if( uwGUSPort == 0 )
1.1.1.2 ! root 1176: return;
1.1 root 1177:
1178: #ifdef DEBUG
1179: fprintf( stderr, "- Interrupt aufgetreten. Zeit: %lf\n", ((double)clock())/((double)CLOCKS_PER_SEC) );
1180: #endif
1181:
1182: for(;;)
1183: {
1184:
1.1.1.2 ! root 1185: ubIntArt = ReadGUSb( GUS_IRQSTATE );
1.1 root 1186:
1.1.1.2 ! root 1187: #ifdef DEBUG
! 1188: fprintf( stderr, " IRQ-Status (2x6): $%X\n", ubIntArt );
! 1189: #endif
1.1 root 1190:
1191:
1.1.1.2 ! root 1192: if( ubIntArt == 0 ) // Fertig ?
! 1193: break;
1.1 root 1194:
1.1.1.2 ! root 1195: if( ubIntArt & 128 ) // TC-IRQ ?
! 1196: {
1.1 root 1197:
1.1.1.2 ! root 1198: WriteGUSb( GUS_COMMAND, GUS_CMD_DRAMDMACTRL );
! 1199: if( ReadGUSb( GUS_DATAHI ) & 0x40 )
! 1200: {
! 1201: #ifdef DEBUG
! 1202: fprintf( stderr, " - Bearbeite DMA-Interrupt\n" );
! 1203: #endif
1.1 root 1204:
1.1.1.2 ! root 1205: bDMAInProgress = FALSE;
1.1 root 1206:
1.1.1.2 ! root 1207: }
1.1 root 1208:
1.1.1.2 ! root 1209: WriteGUSb( GUS_COMMAND, GUS_CMD_SAMPLECTRL );
! 1210: if( ReadGUSb( GUS_DATAHI ) & 0x40 )
! 1211: {
! 1212: #ifdef DEBUG
! 1213: fprintf( stderr, " - Bearbeite Sample-Interrupt\n" );
! 1214: #endif
1.1 root 1215:
1.1.1.2 ! root 1216: }
1.1 root 1217:
1.1.1.2 ! root 1218: }
1.1 root 1219:
1.1.1.2 ! root 1220: if( ubIntArt & 3 )
! 1221: {
! 1222: #ifdef DEBUG
! 1223: fprintf( stderr, " - Bearbeite MIDI-IRQ\n" );
! 1224: #endif
1.1 root 1225:
1.1.1.2 ! root 1226: }
1.1 root 1227:
1.1.1.2 ! root 1228: if( ubIntArt & 64 )
! 1229: {
! 1230: #ifdef DEBUG
! 1231: fprintf( stderr, " - Bearbeite VOLUME-IRQ\n" );
! 1232: #endif
! 1233: GUS_WorkOnVoices();
1.1 root 1234:
1235:
1.1.1.2 ! root 1236: }
1.1 root 1237:
1.1.1.2 ! root 1238: if( ubIntArt & 32 )
! 1239: {
! 1240: #ifdef DEBUG
! 1241: fprintf( stderr, " - Bearbeite WAVETABLE-IRQ\n" );
! 1242: #endif
! 1243: GUS_WorkOnVoices();
1.1 root 1244:
1.1.1.2 ! root 1245: }
1.1 root 1246:
1247:
1.1.1.2 ! root 1248: if( ubIntArt & 4 ) // Timer 1?
! 1249: {
! 1250: #ifdef DEBUG
! 1251: fprintf( stderr, " - Bearbeite Timer 1-IRQ\n" );
! 1252: #endif
1.1 root 1253:
1.1.1.2 ! root 1254: WriteGUSb( GUS_COMMAND, GUS_CMD_TIMERCTRL );
! 1255: ubTemp = ReadGUSb( GUS_DATAHI );
1.1 root 1256:
1.1.1.2 ! root 1257: WriteGUSb( GUS_COMMAND, GUS_CMD_TIMERCTRL );
! 1258: WriteGUSb( GUS_DATAHI, ubTemp & (~4) ); // Timer 1 aus
! 1259: }
1.1 root 1260:
1.1.1.2 ! root 1261: if( ubIntArt & 8 ) // Timer 2?
! 1262: {
! 1263: #ifdef DEBUG
! 1264: fprintf( stderr, " - Bearbeite Timer 2-IRQ\n" );
! 1265: #endif
1.1 root 1266:
1.1.1.2 ! root 1267: WriteGUSb( GUS_COMMAND, GUS_CMD_TIMERCTRL );
! 1268: ubTemp = ReadGUSb( GUS_DATAHI );
1.1 root 1269:
1.1.1.2 ! root 1270: WriteGUSb( GUS_COMMAND, GUS_CMD_TIMERCTRL );
! 1271: WriteGUSb( GUS_DATAHI, ubTemp & (~8) ); // Timer 2 aus
! 1272: }
1.1 root 1273: }
1274:
1275: #ifdef DEBUG
1276: fprintf( stderr, "- Interruptende\n\n" );
1277: #endif
1278:
1279: if( ubGUSGF1Int > 7 )
1.1.1.2 ! root 1280: outportb( 0xA0, 0x20 );
1.1 root 1281:
1282: outportb( 0x20, 0x20 );
1283:
1284: }
1285:
1286:
1287: // Dummy-Routine zum erkennen des Programmendes
1288:
1289: void GUS_DummyFunc( void )
1290: {
1291: ;
1292: }
1293:
1294:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.