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