home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / dbp.c < prev    next >
C/C++ Source or Header  |  1994-08-06  |  20KB  |  662 lines

  1. /*      DBP.C
  2.  *
  3.  * MIDAS debug module player
  4.  *
  5.  * Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6.  *
  7.  * This file is part of the MIDAS Sound System, and may only be
  8.  * used, modified and distributed under the terms of the MIDAS
  9.  * Sound System license, LICENSE.TXT. By continuing to use,
  10.  * modify or distribute this file you indicate that you have
  11.  * read the license and understand and accept it fully.
  12. */
  13.  
  14.  
  15. /* Much of this code is simply copied from MIDAS.C, with some reorganization
  16.    and conditional compilation for easier debugging */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <conio.h>
  21. #include <alloc.h>
  22. #include "midas.h"
  23.  
  24.  
  25. // #define USETIMER                        /* use timer for playing */
  26. // #define HWSD                            /* hard-wired Sound Device pointer */
  27. // #define HWMP                            /* hard-wired Module Player */
  28.  
  29.  
  30. SoundDevice     *SD;                    /* current Sound Device */
  31. ModulePlayer    *MP;                    /* current Module Player */
  32.  
  33. #ifndef HWSD
  34. SoundDevice     *SoundDevices[NUMSDEVICES] =
  35.     { &GUS,                             /* array of pointers to all Sound */
  36.       &PAS,                             /* Devices, in numbering and */
  37.       &WSS,                             /* detection order - GUS is SD #1 */
  38.       &SB,                              /* and will be detected first */
  39.       &NSND };
  40. #endif
  41.  
  42. #ifndef HWMP
  43.     /* pointers to all Module Players: */
  44. ModulePlayer    *ModulePlayers[NUMMPLAYERS] =
  45.     { &mpS3M,
  46.       &mpMOD };
  47.  
  48.     /* Amiga Loop Emulation flags for Module Players: */
  49. short           mpALE[NUMMPLAYERS] =
  50.     { 0, 1 };
  51.  
  52. #endif
  53.  
  54.  
  55. static int      disableEMS;             /* should EMS usage be disabled? */
  56. static ushort   sdNum;                  /* Sound Device number (0xFFFF for
  57.                                            autodetect) */
  58. static ushort   ioPort;                 /* I/O port number (0xFFFF for
  59.                                            autodetect/default) */
  60. static uchar    IRQ;                    /* IRQ number (0xFF for autodetect/
  61.                                            default) */
  62. static uchar    DMA;                    /* DMA channel number (0xFF for
  63.                                            autodetect/default) */
  64. static ushort   mixRate;                /* mixing rate */
  65. static ushort   mode;                   /* forced output mode */
  66.  
  67. static int      emsInitialized;         /* is EMS heap manager initialized? */
  68. static int      tmrInitialized;         /* is TempoTimer initialized? */
  69. static int      sdInitialized;          /* is Sound Device initialized? */
  70. static int      sdChOpen;               /* are Sound Device channels open? */
  71. static int      vuInitialized;          /* are real VU-meters initialized? */
  72. static int      mpInit;                 /* is Module Player initialized? */
  73. static int      mpPlay;                 /* is Module Player playing? */
  74. static int      mpInterrupt;            /* is Module Player interrupt set? */
  75.  
  76.  
  77. char *usage =
  78. "USAGE:\tDBP\t<filename>\n";
  79.  
  80.  
  81.  
  82. void CloseMIDAS(void);
  83.  
  84.  
  85. /****************************************************************************\
  86. *
  87. * Function:     void Error(char *msg)
  88. *
  89. * Description:  Prints an error message to stderr, uninitializes MIDAS and
  90. *               exits to DOS
  91. *
  92. * Input:        char *msg               Pointer to error message string
  93. *
  94. \****************************************************************************/
  95.  
  96. void Error(char *msg)
  97. {
  98.     textmode(C80);
  99.     fprintf(stderr, "Error: %s\n", msg);
  100. #ifdef DEBUG
  101.     errPrintList();                     /* print error list */
  102. #endif
  103.     CloseMIDAS();
  104.     exit(EXIT_FAILURE);
  105. }
  106.  
  107.  
  108.  
  109. /****************************************************************************\
  110. *
  111. * Function:     void UninitError(char *msg)
  112. *
  113. * Description:  Prints an error message to stderr and exits to DOS without
  114. *               uninitializing MIDAS. This function should only be used
  115. *               from CloseMIDAS();
  116. *
  117. * Input:        char *msg               Pointer to error message string
  118. *
  119. \****************************************************************************/
  120.  
  121. void UninitError(char *msg)
  122. {
  123.     textmode(C80);
  124.     fprintf(stderr, "FATAL: Uninitialization error: %s\n", msg);
  125. #ifdef DEBUG
  126.     errPrintList();                     /* print error list */
  127. #endif
  128.     abort();
  129. }
  130.  
  131.  
  132. /****************************************************************************\
  133. *
  134. * Function:     void DetectSD(void)
  135. *
  136. * Description:  Attempts to detect a Sound Device. Sets the global variable
  137. *               SD to point to the detected Sound Device or NULL if no
  138. *               Sound Device was detected
  139. *
  140. \****************************************************************************/
  141.  
  142. void DetectSD(void)
  143. {
  144.     int         dsd;
  145.     int         dResult;
  146.     int         error;
  147.  
  148. #ifdef HWSD
  149.     SD = &SB;                           /* use Pro Audio Spectrum */
  150.     return;
  151. #else
  152.  
  153.     SD = NULL;                          /* no Sound Device detected yet */
  154.     dsd = 0;                            /* start from first Sound Device */
  155.  
  156.     /* search through Sound Devices until a Sound Device is detected: */
  157.     while ( (SD == NULL) && (dsd < NUMSDEVICES) )
  158.     {
  159.         /* attempt to detect current SD: */
  160.         if ( (error = (*SoundDevices[dsd]->Detect)(&dResult)) != OK )
  161.             Error(errorMsg[error]);
  162.         if ( dResult == 1 )
  163.         {
  164.             sdNum = dsd;                /* Sound Device detected */
  165.             SD = SoundDevices[dsd];     /* point SD to this Sound Device */
  166.         }
  167.         dsd++;                          /* try next Sound Device */
  168.     }
  169. #endif
  170. }
  171.  
  172.  
  173.  
  174. /****************************************************************************\
  175. *
  176. * Function:     void InitMIDAS(void);
  177. *
  178. * Description:  Initializes MIDAS Sound System
  179. *
  180. \****************************************************************************/
  181.  
  182. void InitMIDAS(void)
  183. {
  184.     int         error, result;
  185.  
  186.     emsInitialized = 0;                 /* EMS heap manager is not
  187.                                            initialized yet */
  188.     tmrInitialized = 0;                 /* TempoTimer is not initialized */
  189.     sdInitialized = 0;                  /* Sound Device is not initialized */
  190.     sdChOpen = 0;                       /* Sound Device channels are not
  191.                                            open */
  192.     vuInitialized = 0;                  /* VU meter are not initialized */
  193.     mpInit = 0;                         /* Module Player is not initialized */
  194.     mpPlay = 0;                         /* Module Player is not playing */
  195.     mpInterrupt = 0;                    /* No Module Player interrupt */
  196.  
  197.     if ( !disableEMS )                  /* is EMS usage disabled? */
  198.     {
  199.         /* Initialize EMS Heap Manager: */
  200.         if ( (error = emsInit(&emsInitialized)) != OK )
  201.             Error(errorMsg[error]);
  202.  
  203.         /* was EMS Heap Manager initialized? */
  204.         if ( emsInitialized == 1 )
  205.         {
  206.             useEMS = 1;                 /* yes, use EMS memory, but do not */
  207.             forceEMS = 0;               /* force its usage */
  208.         }
  209.         else
  210.         {
  211.             useEMS = 0;                 /* no, do not use EMS memory */
  212.             forceEMS = 0;
  213.         }
  214.     }
  215.     else
  216.     {
  217.         useEMS = 0;                     /* EMS disabled - do not use it */
  218.         forceEMS = 0;
  219.     }
  220.  
  221.  
  222.     if ( sdNum == 0xFFFF )             /* has a Sound Device been selected? */
  223.     {
  224.         DetectSD();                     /* attempt to detect Sound Device */
  225.         if ( SD == NULL )
  226.             Error("Unable to detect Sound Device");
  227.     }
  228.     else
  229.     {
  230.         #ifdef HWSD
  231.         SD = &PAS;
  232.         #else
  233.         SD = SoundDevices[sdNum];       /* use Sound Device sdNum */
  234.         #endif
  235.  
  236.         /* Sound Device number was forced, but if no I/O port, IRQ or DMA
  237.            number has been set, try to autodetect the values for this Sound
  238.            Device. If detection fails, use default values */
  239.  
  240.         if ( (ioPort == 0xFFFF) && (IRQ == 0xFF) && (DMA == 0xFF) )
  241.             if ( (error = SD->Detect(&result)) != OK )
  242.                 Error(errorMsg[error]);
  243.             if ( result != 1 )
  244.                 Error("Unable to detect Sound Device values");
  245.     }
  246.  
  247.     if ( ioPort != 0xFFFF )             /* has an I/O port been set? */
  248.         SD->port = ioPort;              /* if yes, set it to Sound Device */
  249.     if ( IRQ != 0xFF )                  /* what about IRQ number? */
  250.         SD->IRQ = IRQ;
  251.     if ( DMA != 0xFF )                  /* or DMA channel number */
  252.         SD->DMA = DMA;
  253.  
  254. #ifdef USETIMER
  255.     /* initialize TempoTimer: */
  256.     if ( (error = tmrInit()) != OK )    /* initialize TempoTimer */
  257.         Error(errorMsg[error]);
  258.  
  259.     tmrInitialized = 1;                 /* TempoTimer initialized */
  260. #endif
  261.  
  262.     /* initialize Sound Device: */
  263.     if ( (error = SD->Init(mixRate, mode)) != OK )
  264.         Error(errorMsg[error]);
  265.  
  266.     sdInitialized = 1;                  /* Sound Device initialized */
  267.  
  268. #ifdef REALVUMETERS
  269.     if ( realVU )
  270.     {
  271.         /* initialize real VU-meters: */
  272.         if ( (error = vuInit()) != OK )
  273.             Error(errorMsg[error]);
  274.  
  275.         vuInitialized = 1;
  276.     }
  277. #endif
  278. }
  279.  
  280.  
  281.  
  282. /****************************************************************************\
  283. *
  284. * Function:     void CloseMIDAS(void)
  285. *
  286. * Description:  Uninitializes MIDAS Sound System
  287. *
  288. \****************************************************************************/
  289.  
  290. void CloseMIDAS(void)
  291. {
  292.     int         error;
  293.  
  294.     /* Note that as this function has been added to atexit() chain, it may
  295.        not cause the program to exit by, for example, calling midasError() */
  296.  
  297. #ifdef USETIMER
  298.     /* if Module Player interrupt is running, remove it: */
  299.     if ( mpInterrupt )
  300.     {
  301.         if ( (error = MP->RemoveInterrupt()) != OK )
  302.             UninitError(errorMsg[error]);
  303.         mpInterrupt = 0;
  304.     }
  305. #endif
  306.  
  307.     /* if Module Player is playing, stop it: */
  308.     if ( mpPlay )
  309.     {
  310.         if ( (error = MP->StopModule()) != OK )
  311.             UninitError(errorMsg[error]);
  312.         mpPlay = 0;
  313.     }
  314.  
  315.     /* if Module Player has been initialized, uninitialize it: */
  316.     if ( mpInit )
  317.     {
  318.         if ( (error = MP->Close()) != OK )
  319.             UninitError(errorMsg[error]);
  320.         mpInit = 0;
  321.         MP = NULL;
  322.     }
  323.  
  324. #ifdef REALVUMETERS
  325.     /* if real VU-meters have been initialized, uninitialize them: */
  326.     if ( vuInitialized )
  327.     {
  328.         if ( (error = vuClose()) != OK )
  329.             UninitError(errorMsg[error]);
  330.         vuInitialized = 0;
  331.     }
  332. #endif
  333.  
  334.     /* if Sound Device channels are open, close them: */
  335.     if ( sdChOpen )
  336.     {
  337.         if ( (error = SD->CloseChannels()) != OK )
  338.             UninitError(errorMsg[error]);
  339.         sdChOpen = 0;
  340.     }
  341.  
  342.     /* if Sound Device is initialized, uninitialize it: */
  343.     if ( sdInitialized )
  344.     {
  345.         if ( (error = SD->Close()) != OK )
  346.             UninitError(errorMsg[error]);
  347.         sdInitialized = 0;
  348.         SD = NULL;
  349.     }
  350.  
  351.     /* if TempoTimer is initialized, uninitialize it: */
  352.     if ( tmrInitialized )
  353.     {
  354.         if ( (error = tmrClose()) != OK )
  355.             UninitError(errorMsg[error]);
  356.         tmrInitialized = 0;
  357.     }
  358.  
  359.     /* if EMS Heap Manager is initialized, uninitialize it: */
  360.     if ( emsInitialized )
  361.     {
  362.         if ( (error = emsClose()) != OK )
  363.             UninitError(errorMsg[error]);
  364.         emsInitialized = 0;
  365.     }
  366. }
  367.  
  368.  
  369.  
  370. /****************************************************************************\
  371. *
  372. * Function:     void SetDefaults(void)
  373. *
  374. * Description:  Initializes MIDAS Sound System variables to their default
  375. *               states. MUST be the first MIDAS function called.
  376. *
  377. \****************************************************************************/
  378.  
  379. void SetDefaults(void)
  380. {
  381.     emsInitialized = 0;                 /* EMS heap manager is not
  382.                                            initialized yet */
  383.     tmrInitialized = 0;                 /* TempoTimer is not initialized */
  384.     sdInitialized = 0;                  /* Sound Device is not initialized */
  385.     sdChOpen = 0;                       /* Sound Device channels are not
  386.                                            open */
  387.     vuInitialized = 0;                  /* VU meter are not initialized */
  388.     mpInit = 0;                         /* Module Player is not initialized */
  389.     mpPlay = 0;                         /* Module Player is not playing */
  390.     mpInterrupt = 0;                    /* No Module Player interrupt */
  391.  
  392.  
  393.     ptTempo = 1;                        /* enable ProTracker BPM tempos */
  394.     usePanning = 1;                     /* enable ProTracker panning cmds */
  395.     surround = 0;                       /* disable surround to save GUS mem */
  396.     realVU = 1;                         /* disable real VU-meters */
  397.  
  398.     disableEMS = 0;                     /* do not disable EMS usage */
  399.     sdNum = 0x0FFFF;                    /* no Sound Device forced */
  400.     ioPort = 0xFFFF;                    /* no I/O port forced */
  401.     IRQ = 0xFF;                         /* no IRQ number forced */
  402.     DMA = 0xFF;                         /* no DMA channel number forced */
  403.     mode = 0;                           /* no output mode forced */
  404.     mixRate = 44100;                    /* attempt to use 44100Hz mixing
  405.                                            rate */
  406.  
  407.     SD = NULL;                          /* point SD and MP to NULL for */
  408.     MP = NULL;                          /* safety */
  409. }
  410.  
  411.  
  412.  
  413. /****************************************************************************\
  414. *
  415. * Function:     mpModule *PlayModule(char *fileName)
  416. *
  417. * Description:  Loads a module into memory, points MP to the correct Module
  418. *               Player and starts playing it.
  419. *
  420. * Input:        char *fileName          Pointer to module file name
  421. *
  422. * Returns:      Pointer to module structure. This function can not fail,
  423. *               as it will call Error() to handle all error situations.
  424. *
  425. \****************************************************************************/
  426.  
  427. mpModule *PlayModule(char *fileName)
  428. {
  429.     uchar       *header;
  430.     FILE        *f;
  431.     mpModule    *module;
  432.     short       numChans;
  433.     int         error, mpNum, recognized;
  434.  
  435.     if ( (error = memAlloc(MPHDRSIZE, (void**) &header)) != OK )
  436.         Error(errorMsg[error]);
  437.  
  438.     if ( (f = fopen(fileName, "rb")) == NULL )
  439.         Error("Unable to open module file");
  440.  
  441.     if ( fread(header, MPHDRSIZE, 1, f) != 1 )      /* read MPHDRSIZE bytes */
  442.         Error("Unable to read module header");      /* of module header */
  443.  
  444. #ifdef HWMP
  445.     MP = &mpS3M;
  446.     ALE = 0;
  447. #else
  448.  
  449.     /* Search through all Module Players to find one that recognizes
  450.        file header: */
  451.     mpNum = 0; MP = NULL;
  452.     while ( (mpNum < NUMMPLAYERS) && (MP == NULL) )
  453.     {
  454.         if ( (error = ModulePlayers[mpNum]->Identify(header, &recognized))
  455.             != OK )
  456.             Error(errorMsg[error]);
  457.         if ( recognized )
  458.         {
  459.             MP = ModulePlayers[mpNum];
  460.             ALE = mpALE[mpNum];
  461.         }
  462.         mpNum++;
  463.     }
  464.  
  465.     if ( MP == NULL )
  466.         Error("Unknown module format");
  467. #endif
  468.  
  469.     /* deallocate module header: */
  470.     if ( (error = memFree(header)) != OK )
  471.         Error(errorMsg[error]);
  472.     fclose(f);
  473.  
  474.     /* initialize module player: */
  475.     if ( (error = MP->Init(SD)) != OK )
  476.         Error(errorMsg[error]);
  477.     mpInit = 1;
  478.  
  479.     /* load module: */
  480.     if ( (error = MP->LoadModule(fileName, SD, (mpModule**) &module)) != OK )
  481.         Error(errorMsg[error]);
  482.  
  483.     numChans = module->numChans;
  484.  
  485.     /* open Sound Device channels: */
  486.     if ( (error = SD->OpenChannels(numChans)) != OK )
  487.         Error(errorMsg[error]);
  488.     sdChOpen = 1;
  489.  
  490.     /* start playing module using first numChans channels and looping the
  491.        whole song */
  492.     if ( (error = MP->PlayModule(module, 0, numChans, 0, 32767)) != OK )
  493.         Error(errorMsg[error]);
  494.     mpPlay = 1;
  495.  
  496. #ifdef USETIMER
  497.     /* start playing using the timer: */
  498.     if ( (error = MP->SetInterrupt()) != OK )
  499.         Error(errorMsg[error]);
  500. #endif
  501.  
  502.     return module;
  503. }
  504.  
  505.  
  506. /****************************************************************************\
  507. *
  508. * Function:     void StopModule(mpModule *module)
  509. *
  510. * Description:  Stops playing a module, deallocates it and uninitializes
  511. *               the Module Player.
  512. *
  513. \****************************************************************************/
  514.  
  515. void StopModule(mpModule *module)
  516. {
  517.     int         error;
  518.  
  519. #ifdef USETIMER
  520.     /* remove Module Player interrupt: */
  521.     if ( (error = MP->RemoveInterrupt()) != OK )
  522.         Error(errorMsg[error]);
  523.     mpInterrupt = 0;
  524. #endif
  525.  
  526.     /* stop playing the module: */
  527.     if ( (error = MP->StopModule()) != OK )
  528.         Error(errorMsg[error]);
  529.     mpPlay = 0;
  530.  
  531.     /* deallocate module: */
  532.     if ( (error = MP->FreeModule(module, SD)) != OK )
  533.         Error(errorMsg[error]);
  534.  
  535.     /* uninitialize Module Player: */
  536.     if ( (error = MP->Close()) != OK )
  537.         Error(errorMsg[error]);
  538.     mpInit = 0;
  539.     MP = NULL;                          /* point MP to NULL for safety */
  540.  
  541.     /* close Sound Device channels: */
  542.     if ( (error = SD->CloseChannels()) != OK )
  543.         Error(errorMsg[error]);
  544.     sdChOpen = 0;
  545. }
  546.  
  547.  
  548.  
  549. void WaitVR(void)
  550. {
  551. asm     mov     dx,03DAh
  552. wvr:
  553. asm {   in      al,dx
  554.         test    al,8
  555.         jz      wvr
  556. }
  557. }
  558.  
  559.  
  560.  
  561. void WaitDE(void)
  562. {
  563. asm     mov     dx,03DAh
  564. wde:
  565. asm {   in      al,dx
  566.         test    al,1
  567.         jnz     wde
  568. }
  569. }
  570.  
  571.  
  572.  
  573. void SetBorder(uchar color)
  574. {
  575. asm {   mov     dx,03C0h
  576.         mov     al,31h
  577.         out     dx,al
  578.         mov     al,color
  579.         out     dx,al
  580. }
  581. }
  582.  
  583.  
  584. ulong           free1, free2;
  585.  
  586.  
  587. void showheap(void)
  588. {
  589.     free2 = coreleft();
  590.     cprintf("%lu bytes memory free - %lu bytes used.\r\n",
  591.         free2, free1-free2);
  592.  
  593.     if ( heapcheck() != _HEAPOK )
  594.         cputs("HEAP CORRUPTED - PREPARE FOR SYSTEM CRASH!\r\n");
  595. }
  596.  
  597.  
  598.  
  599. int main(int argc, char *argv[])
  600. {
  601.     int         error;
  602.     int         plMusic;
  603.     mpModule    *module;
  604.  
  605.  
  606.     if ( argc != 2 )
  607.     {
  608.         puts(usage);
  609.         exit(EXIT_SUCCESS);
  610.     }
  611.  
  612.     printf("%lu bytes free\n", free1 = coreleft());
  613.     SetDefaults();
  614.     InitMIDAS();
  615.     showheap();
  616.     module = PlayModule(argv[1]);
  617.     puts("Playing - press any key to stop");
  618.     showheap();
  619.  
  620.     while ( !kbhit() )
  621.     {
  622. #ifndef USETIMER
  623.         WaitVR();
  624.         WaitDE();
  625.         SetBorder(15);
  626.         if ( SD->tempoPoll == 1 )
  627.         {
  628.             if ( (error = SD->Play(&plMusic)) != OK )
  629.                 Error(errorMsg[error]);
  630.             SetBorder(14);
  631.             if ( (error = MP->Play()) != OK )
  632.                 Error(errorMsg[error]);
  633.         }
  634.         else
  635.         {
  636.             dmaGetPos(&dsmBuffer, &dsmDMAPos);
  637.             if ( (error = SD->Play(&plMusic)) != OK )
  638.                 Error(errorMsg[error]);
  639.  
  640.             while ( plMusic )
  641.             {
  642.                 SetBorder(14);
  643.                 if ( (error = MP->Play()) != OK )
  644.                     Error(errorMsg[error]);
  645.                 SetBorder(15);
  646.                 if ( (error = SD->Play(&plMusic)) != OK )
  647.                     Error(errorMsg[error]);
  648.             }
  649.         }
  650.         SetBorder(0);
  651. #endif
  652.     }
  653.  
  654.     getch();
  655.     StopModule(module);
  656.     showheap();
  657.     CloseMIDAS();
  658.     showheap();
  659.  
  660.     return 0;
  661. }
  662.