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