Annotation of uae/src/md-i386-dos/sound/gus.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.