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