home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / sndbords / proaudio / pcmtlsrc / tpcm.arj / TPCM.C < prev    next >
C/C++ Source or Header  |  1992-09-09  |  23KB  |  1,179 lines

  1. ;    /*\
  2. ;    |*| $Author:   BCRANE  $
  3. ;    |*|
  4. ;    |*| $Date:   09 Sep 1992 14:01:44  $
  5. ;    |*|
  6. ;    |*| $Header:   X:/sccs/sdkapp/tpcm.c_v   1.5   09 Sep 1992 14:01:44   BCRANE  $
  7. ;    |*|
  8. ;    |*| $Log:   X:/sccs/sdkapp/tpcm.c_v  $
  9.  * 
  10.  *    Rev 1.5   09 Sep 1992 14:01:44   BCRANE
  11.  * added "animation" to DOVIDEO=2
  12.  * 
  13.  *    Rev 1.4   31 Aug 1992 19:09:06   BCRANE
  14.  * added proper support  for 16 bit
  15.  * 
  16.  *    Rev 1.3   31 Aug 1992 16:39:08   BCRANE
  17.  * added U,D donothing() keys
  18.  * 
  19.  *    Rev 1.2   31 Aug 1992 10:51:40   BCRANE
  20.  * changed c,C and added r in donothing()
  21.  * added check for escape to break out early
  22.  * 
  23.  *    Rev 1.1   31 Aug 1992 09:34:54   BCRANE
  24.  * added support for 16-bit 
  25.  * 
  26.  *    Rev 1.0   29 Jul 1992 16:58:14   BCRANE
  27.  * Initial revision.
  28. ;    |*|
  29. ;    |*| $Logfile:   X:/sccs/sdkapp/tpcm.c_v  $
  30. ;    |*|
  31. ;    |*| $Modtimes$
  32. ;    |*|
  33. ;    |*| $Revision:   1.5  $
  34. ;    |*|
  35. ;    |*| $Workfile:   tpcm.c  $
  36. ;    |*|
  37. ;    \*/
  38.  
  39.  
  40. /* Copyright (c) 1992.  Media Vision, Inc.  All Rights Reserved. */
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <fcntl.h>
  44. #include <io.h>
  45. #include <string.h>
  46. #include <process.h>
  47. #include <conio.h>
  48. #include <dos.h>
  49. #include <malloc.h>
  50. #include <bios.h>
  51. #include <graph.h>
  52.  
  53. typedef unsigned char uchar;
  54. typedef unsigned int uint;
  55. typedef unsigned long ulong;
  56.  
  57. #include "pcmio.h"
  58. #include "sndfile.h"
  59.  
  60. #define ERROR -1
  61. #define OKAY 0
  62. #define YES 1
  63. #define NO 0
  64.  
  65. #define BADARGORDER 7
  66. #define BADINPFILE 8
  67. #define BADOUTFILE 9
  68. #define BADOPTION 10
  69. #define BADHARDWARE 11
  70. #define BADPCMBUFFER 12
  71. #define BADPCMBUFDIVS 13
  72.  
  73. int DEBUG;
  74. int BEQUIET;
  75. int USEMONO;
  76. int LOOPING;
  77. int STEREO;
  78. int CYCLESPEED;
  79. int USEPALETTE;
  80.  
  81. int DOVIDEO;
  82. int USERFUNC;
  83. int DORESIDENT;
  84. int INPFILE;
  85. int SPECIALCASE;
  86.  
  87. long SAMPLERATE;
  88.  
  89. uint SBSIZE;
  90. uint PCMBUFKAYS;
  91. uint PCMBUFSIZE;
  92. uint PCMBUFDIVS;
  93. uint BLOCKSREAD;
  94.  
  95. int PCMPAUSED;
  96.  
  97. int volatile OURSTATFLAG;
  98.  
  99. char far *OURDMABUF;
  100. char huge *HUGEDMABUF;
  101.  
  102. static char *inpname;
  103. static char *outname;
  104.  
  105. int fhinp;
  106.  
  107. #define V2X    145
  108. #define V2Y    74
  109. #define V2W    12
  110. #define V2H    4
  111. #define V2D 4
  112. char v2fun[V2H+ V2D][V2W];
  113. int v2funlevel[2];
  114.  
  115.  
  116. #include "protos.h"
  117.  
  118. //char far *doInitMVSound(void);
  119. //int doInitPCM(void);
  120. //int doPCMInfo(long, int);
  121. //char far *doDMABuffer(char far *, uint, uint);
  122. //void far *doUserFunc(void far *);
  123. //int doPCMPlay(void);
  124. //int doPCMRecord(void);
  125. //int doPausePCM(void);
  126. //int doResumePCM(void);
  127. //int doStopPCM(void);
  128. //int doRemovePCM(void);
  129. char far *doFindDMABuffer(char huge *, uint);
  130.  
  131. char *syntax=
  132.     "Syntax: tpcm [-dqmls] [-iinpname] [-B#][-D#][-R#][-F[#]][-V[#]] [wavfiles ...]\n"
  133.     "Options:\n"
  134.     "-d\tdebug mode, output status\n"
  135.     "-q\tquiet mode (no sound)\n"
  136.     "-m\tuse Monochrome Screen Buffer for DMA\n"
  137.     "-l\tLoop sound continuously\n"
  138.     "-s\ttreat as stereo\n"
  139.     "-i inpname\tinpname= name of input PCM file (use -R and -s)\n"
  140.     "-B#\t#= size of DMA Buffer in kilobytes, default: 2 or 4K if video, else 32K\n"
  141.     "-D#\t#= number of DMA Divisions, default: 2 if video, else 8\n"
  142.     "-R#\t#= default samplerate (decimal) default: 11025\n"
  143.     "-F[#]\t#= User Function # (see ref) default: PCM.COM User Function 0\n"
  144.     "-V[#]\t#= Video Function # (see ref) default: dspmonowav() or dspstereowav()\n"
  145.     "wavfiles ...\tfilenames to play (overrides -R and -s)\n"
  146.     "Note: -iinpname and wavfiles... are mutually exclusive\n"
  147.     ;
  148.  
  149. char vidbuf[320];
  150.  
  151. char *copyright= "Copyright (c) 1992.  Media Vision, Inc.  All Rights Reserved.";
  152. char *programmer= "Bart Crane";
  153.  
  154. /*****************     MAIN  *****************************/
  155. /* main - */
  156. main(int argc, char **argv)
  157. {
  158.     int status;
  159.     BT bt;
  160.     unsigned int br;
  161.  
  162.     if (status= checkforsig())
  163.         {
  164.         fprintf(stderr, "error: driver not installed.\n");
  165.         return(status);
  166.         }
  167.  
  168.     if (status= parse(argc, argv))
  169.         return(status);
  170.  
  171.     if (DOVIDEO)
  172.         initvideo(argv[0], DOVIDEO);
  173.  
  174.     nextfile:
  175.  
  176.     BLOCKSREAD= 0;
  177.     OURSTATFLAG= 0;
  178.  
  179.     if (INPFILE)
  180.         {
  181.         if ((fhinp= open(inpname= argv[INPFILE], O_BINARY| O_RDONLY)) == ERROR)
  182.             {
  183.             if (++INPFILE < argc)
  184.                 goto nextfile;
  185.             if (DOVIDEO)
  186.                 _setvideomode(_DEFAULTMODE);
  187.             if (!DOVIDEO)
  188.                 fprintf(stderr, "%s: input file not found.\n", argv[INPFILE- 1]);
  189.             return(BADINPFILE);
  190.             }
  191.         if (getsndfile(fhinp, inpname, &bt, SAMPLERATE, (STEREO ? 2 : 1)) == ERROR)
  192.             goto skipit;
  193.         }
  194.     else 
  195.         {
  196.         if ((fhinp= open(inpname, O_BINARY| O_RDONLY)) == ERROR)
  197.             {
  198.             if (DOVIDEO)
  199.                 _setvideomode(_DEFAULTMODE);
  200.             if (!DOVIDEO)
  201.                 fprintf(stderr, "%s: input file not found.\n", inpname);
  202.             return(BADINPFILE);
  203.             }
  204.         bt.fhidx= fhinp;
  205.         bt.foffset= lseek(fhinp, 0L, SEEK_CUR);
  206.         bt.offset= 0;
  207.         bt.size= lseek(fhinp, 0L, SEEK_END);
  208.         lseek(fhinp, bt.foffset, SEEK_SET);
  209.         bt.wf.fmttag= 1;
  210.         bt.wf.channels= STEREO ? 2 : 1;
  211.         bt.wf.samplerate= SAMPLERATE;
  212.         bt.wf.bytespersec= bt.wf.channels* bt.wf.samplerate;
  213.         bt.wf.blockalign= bt.wf.channels;
  214.         bt.wf.datasize= 8;
  215.         }
  216.  
  217.     if (DEBUG)
  218.         {
  219.         printf("%2d  %5ld  %5ld  %6ld  %1d  %1d  %5ld  %5ld  %2d  %2d\n",
  220.             bt.fhidx, bt.foffset, bt.offset, bt.size,
  221.             bt.wf.fmttag, bt.wf.channels, bt.wf.samplerate,
  222.             bt.wf.bytespersec, bt.wf.blockalign, bt.wf.datasize);
  223.         }
  224.  
  225.     if (bt.wf.datasize != 8 && bt.wf.datasize != 16)
  226.         {
  227.         if (!DOVIDEO)
  228.             fprintf(stderr, "error: 8- or 16-bit PCM only.\n");
  229.         goto skipit;
  230.         }
  231.  
  232.     /* if showing video, override PCMBUFKAYS and PCMBUFDIVS */
  233.     /* hopefully, the DMA buffer allocated was at least 4K */
  234.     if (!SPECIALCASE)
  235.         if (DOVIDEO)
  236.             {
  237.             PCMBUFDIVS= 2;
  238.             PCMBUFKAYS= PCMBUFDIVS* bt.wf.channels* (bt.wf.datasize/ 8);
  239.             if (!PCMBUFKAYS) PCMBUFKAYS= 2;
  240.             SBSIZE= (PCMBUFKAYS/ PCMBUFDIVS)* 1024;
  241.             }
  242.  
  243.     if (!BEQUIET)
  244.         if (status= setupsound(&bt))
  245.             {
  246.             if (DOVIDEO)
  247.                 _setvideomode(_DEFAULTMODE);
  248.             if (!DOVIDEO)
  249.                 fprintf(stderr, "error: failure initializing pcm.com via i94f91.\n");
  250.             return(status);
  251.             }
  252.  
  253.     again:
  254.  
  255.     while (OURSTATFLAG < PCMBUFDIVS)
  256.         {
  257.         char far *buf= OURDMABUF+ ((BLOCKSREAD% PCMBUFDIVS)* SBSIZE);
  258.  
  259.         if (DEBUG)
  260.             {
  261.             ulong curoffset= lseek(fhinp, 0, SEEK_CUR);
  262.             printf("%Fp  %3u  %3u  %7lu  ", buf, BLOCKSREAD, OURSTATFLAG, curoffset);
  263.             }
  264.  
  265.         if (!(br= read(fhinp, buf, SBSIZE))) break;
  266.  
  267.         if (DEBUG)
  268.             printf("%5u\n", br);
  269.  
  270.         if (DOVIDEO == 2)
  271.             v2funlevel[BLOCKSREAD& 0x01]= calcenergylevel(buf, SBSIZE, &bt);
  272.  
  273.         BLOCKSREAD++;
  274.         OURSTATFLAG++;
  275.  
  276.         if (br != SBSIZE)
  277.             {
  278.             if (bt.wf.datasize == 8)
  279.                 fillchar(&buf[br], 0x80, SBSIZE- br);
  280.             else
  281.             if (bt.wf.datasize == 16)
  282.                 fillword((int *) &buf[br], 0x00, (SBSIZE- br)/ 2);
  283.             break;
  284.             }
  285.         }
  286.  
  287.     if (PCMPAUSED)
  288.         {
  289.         if (!BEQUIET)
  290.             _asm
  291.                 {
  292.                 push si
  293.                 mov si, 5        ; PlayPCM()
  294.                 int 94h
  295.                 pop si
  296.                 }
  297.         PCMPAUSED= NO;
  298.         }
  299.  
  300.     while (OURSTATFLAG)
  301.         if (OURSTATFLAG < PCMBUFDIVS)
  302.             {
  303.             char far *buf= OURDMABUF+ ((BLOCKSREAD% PCMBUFDIVS)* SBSIZE);
  304.  
  305.             if (DEBUG)
  306.                 {
  307.                 ulong curoffset= lseek(fhinp, 0, SEEK_CUR);
  308.                 printf("%Fp  %3u  %3u  %7lu  ", buf, BLOCKSREAD, OURSTATFLAG, curoffset);
  309.                 }
  310.  
  311.             br= read(fhinp, buf, SBSIZE);
  312.  
  313.             if (DEBUG)
  314.                 printf("%5u\n", br);
  315.  
  316.             if (!br)
  317.                 break;
  318.  
  319.             if (DOVIDEO == 2)
  320.                 {
  321.                 dspv2fun(v2funlevel[(BLOCKSREAD)& 0x01]);
  322.                 v2funlevel[BLOCKSREAD& 0x01]= calcenergylevel(buf, SBSIZE, &bt);
  323.                 }
  324.  
  325.             BLOCKSREAD++;
  326.             OURSTATFLAG++;
  327.  
  328.             if (br != SBSIZE)
  329.                 {
  330.                 if (bt.wf.datasize == 8)
  331.                     fillchar(&buf[br], 0x80, SBSIZE- br);
  332.                 else
  333.                 if (bt.wf.datasize == 16)
  334.                     fillword((int *) &buf[br], 0x00, (SBSIZE- br)/ 2);
  335.                 break;
  336.                 }
  337.             }
  338.         else
  339.             if ((status= donothing()) == 0x1B)
  340.                 goto skipit;
  341.  
  342.     if (LOOPING)
  343.         {
  344.         lseek(fhinp, bt.foffset, SEEK_SET);
  345.         goto again;
  346.         }
  347.  
  348.     while (OURSTATFLAG)
  349.         {
  350.         if (DEBUG)
  351.             {
  352.             printf("%Fp  %3u  %3u  %1d\n", (void far *) 0, BLOCKSREAD, OURSTATFLAG, PCMPAUSED);
  353.             }
  354.         if ((status= donothing()) == 0x1B)
  355.             goto skipit;
  356.         }
  357.  
  358.     skipit:
  359.  
  360.     if (!BEQUIET)
  361.         {
  362.         _asm
  363.             {
  364.             push si
  365.             mov si, 9    ; StopPCM
  366.             int 94h
  367.             pop si
  368.             }
  369.         PCMPAUSED= YES;
  370.         }
  371.  
  372.     close(fhinp);
  373.  
  374.     if (_bios_keybrd(_KEYBRD_READY))
  375.         if ((char) (_bios_keybrd(_KEYBRD_READ)) == 0x1B)
  376.             goto weredone;
  377.  
  378.     if (INPFILE)
  379.         if (++INPFILE < argc)
  380.             {
  381.             int i;
  382.             char *buf= OURDMABUF;
  383.  
  384.             for (i= 0; i < PCMBUFDIVS; i++, buf+= SBSIZE)
  385.                 {
  386.                 if (bt.wf.datasize == 8)
  387.                     fillchar(buf, 0x80, SBSIZE);
  388.                 else
  389.                 if (bt.wf.datasize == 16)
  390.                     fillword((int *) buf, 0x00, SBSIZE/ 2);
  391.                 }
  392.             goto nextfile;
  393.             }
  394.  
  395.     weredone:
  396.  
  397.     if (DOVIDEO)
  398.         _setvideomode(_DEFAULTMODE);
  399.  
  400.     if (!BEQUIET)
  401.         {
  402.         _asm
  403.             {
  404.             push si
  405.             mov si, 10
  406.             int 94h
  407.             pop si
  408.             }
  409.         }
  410.  
  411.     if (HUGEDMABUF)
  412.         hfree(HUGEDMABUF);
  413.  
  414.     if (DEBUG) putchar('\n');
  415.  
  416.     return(OKAY);
  417. }
  418.  
  419. parse(int c, char **v)
  420. {
  421.     int o= 1;
  422.     int i= 0;
  423.  
  424.     if (c == 1 || !strcmp(v[o], "--") || !strcmpi(v[o], "-h") || !strcmp(v[o], "/h"))
  425.         {
  426.         printf("%s", syntax);
  427.         return(1);
  428.         }
  429.  
  430.     while (o < c)
  431.         {
  432.         if (v[o][0] == '-')
  433.             {
  434.             if (INPFILE)
  435.                 {
  436.                 fprintf(stderr, "Error: argument order: options must come before filenames.\n");
  437.                 return(BADARGORDER);
  438.                 }
  439.             switch (v[o][++i])
  440.                 {
  441.                 case '\0': if (i == 1) inpname= "stdin"; o+= (i= 0)+ 1; break;
  442.                 case 'd': DEBUG= YES; break;
  443.                 case 'q': BEQUIET= YES; break;
  444.                 case 'm': if (USEMONO) USEMONO= NO; else USEMONO= YES; break;
  445.                 case 'l': if (LOOPING) LOOPING= NO; else LOOPING= YES; break;
  446.                 case 's': if (STEREO) STEREO= NO; else STEREO= YES; break;
  447.                 case 'c':
  448.                     if (!isdigit(v[o][++i]))
  449.                         CYCLESPEED= 1;
  450.                     else
  451.                         {
  452.                         CYCLESPEED= 0;
  453.                         while (isdigit(v[o][i]))
  454.                             {
  455.                             CYCLESPEED*= 10;
  456.                             CYCLESPEED+= v[o][i++]- '0';
  457.                             }
  458.                         }
  459.                     i--;
  460.                     break;
  461.                 case 'C':
  462.                     if (!isdigit(v[o][++i]))
  463.                         CYCLESPEED= 1;
  464.                     else
  465.                         {
  466.                         CYCLESPEED= 0;
  467.                         while (isdigit(v[o][i]))
  468.                             {
  469.                             CYCLESPEED*= 10;
  470.                             CYCLESPEED+= v[o][i++]- '0';
  471.                             }
  472.                         }
  473.                     i--;
  474.                     CYCLESPEED*= -1;
  475.                     break;
  476.                 case 'p':
  477.                     if (!isdigit(v[o][++i]))
  478.                         USEPALETTE= 1;
  479.                     else
  480.                         {
  481.                         USEPALETTE= 0;
  482.                         while (isdigit(v[o][i]))
  483.                             {
  484.                             USEPALETTE*= 10;
  485.                             USEPALETTE+= v[o][i++]- '0';
  486.                             }
  487.                         }
  488.                     i--;
  489.                     break;
  490.  
  491.                 case '-': inpname= "stdin"; break;
  492.                 case 'i': if (!v[o][++i]) o+= (i= 0)+ 1; inpname= &v[o][i]; o+= (i= 0)+ 1; break;
  493.                 case 'o': if (!v[o][++i]) o+= (i= 0)+ 1; outname= &v[o][i]; o+= (i= 0)+ 1; break;
  494.  
  495.  
  496.                 case 'b':
  497.                 case 'B':
  498.                     SPECIALCASE= 1;
  499.                     PCMBUFKAYS= 0;
  500.                     i++;
  501.                     while (isdigit(v[o][i])) {PCMBUFKAYS*= 10; PCMBUFKAYS+= v[o][i++]- '0'; }
  502.                     i--;
  503.                     break;
  504.  
  505.                 case 'D':
  506.                     SPECIALCASE= 1;
  507.                     PCMBUFDIVS= 0;
  508.                     i++;
  509.                     while (isdigit(v[o][i])) {PCMBUFDIVS*= 10; PCMBUFDIVS+= v[o][i++]- '0'; }
  510.                     i--;
  511.                     if (PCMBUFDIVS <= 1)
  512.                         return(BADPCMBUFDIVS);
  513.                     break;
  514.  
  515.                 case 'r':
  516.                 case 'R':
  517.                     SAMPLERATE= 0;
  518.                     i++;
  519.                     while (isdigit(v[o][i])) {SAMPLERATE*= 10; SAMPLERATE+= v[o][i++]- '0'; }
  520.                     i--;
  521.                     break;
  522.  
  523.                 case 'S':
  524.                     FP_SEG(OURDMABUF)= 0;
  525.                     i++;
  526.                     while (isxdigit(v[o][i]))
  527.                         {
  528.                         FP_SEG(OURDMABUF)*= 16;
  529.                         if (v[o][i] >= '0' && v[o][i] <= '9')
  530.                             FP_SEG(OURDMABUF)+= v[o][i++]- '0';
  531.                         else if (v[o][i] >= 'a' && v[o][i] <= 'f')
  532.                             FP_SEG(OURDMABUF)+= v[o][i++]- 'a'+ 10;
  533.                         else if (v[o][i] >= 'A' && v[o][i] <= 'F')
  534.                             FP_SEG(OURDMABUF)+= v[o][i++]- 'A'+ 10;
  535.                         }
  536.                     i--;
  537.                     break;
  538.  
  539.                 case 'O':
  540.                     FP_OFF(OURDMABUF)= 0;
  541.                     i++;
  542.                     while (isxdigit(v[o][i]))
  543.                         {
  544.                         FP_OFF(OURDMABUF)*= 16;
  545.                         if (v[o][i] >= '0' && v[o][i] <= '9')
  546.                             FP_OFF(OURDMABUF)+= v[o][i++]- '0';
  547.                         else if (v[o][i] >= 'a' && v[o][i] <= 'f')
  548.                             FP_OFF(OURDMABUF)+= v[o][i++]- 'a'+ 10;
  549.                         else if (v[o][i] >= 'A' && v[o][i] <= 'F')
  550.                             FP_OFF(OURDMABUF)+= v[o][i++]- 'A'+ 10;
  551.                         }
  552.                     i--;
  553.                     break;
  554.  
  555.                 case 'v':
  556.                 case 'V':
  557.                     PCMBUFKAYS= 4;
  558.                     PCMBUFDIVS= 4;
  559.                     i++;
  560.                     if (isdigit(v[o][i]))
  561.                         while (isdigit(v[o][i])) {DOVIDEO*= 10; DOVIDEO+= v[o][i++]- '0'; }
  562.                     else
  563.                         DOVIDEO= 1;
  564.                     i--;
  565.                     break;
  566.  
  567.                 case 'f':
  568.                 case 'F':
  569.                     i++;
  570.                     if (isdigit(v[o][i]))
  571.                         while (isdigit(v[o][i])) {USERFUNC*= 10; USERFUNC+= v[o][i++]- '0'; }
  572.                     else
  573.                         USERFUNC= 1;
  574.                     i--;
  575.                     break;
  576.  
  577.  
  578.                 default:
  579.                     fprintf(stderr, "%c in %s: invalid option.\n", v[o][i], v[o]);
  580.                     return(BADOPTION);
  581.                 }
  582.             }
  583.         else
  584.             {
  585.             if (!INPFILE && !inpname)
  586.                 {
  587.                 INPFILE= o;
  588.                 inpname= v[o];
  589.                 }
  590.             o+= (i= 0)+ 1;
  591.             }
  592.         }
  593.  
  594.     if (!inpname)
  595.         return(BADINPFILE);
  596.  
  597.     if (!SAMPLERATE)
  598.         SAMPLERATE= 11025;
  599.  
  600.     if (PCMBUFKAYS < 4)
  601.         if (DOVIDEO)
  602.             PCMBUFKAYS= 4;
  603.         else
  604.         if (USEMONO)
  605.             PCMBUFKAYS= 32;
  606.         else
  607.             PCMBUFKAYS= 16;
  608.  
  609.     if (PCMBUFDIVS < 2)
  610.         if (DOVIDEO)
  611.             PCMBUFDIVS= 2;
  612.         else
  613.             PCMBUFDIVS= 8;
  614.  
  615.     PCMBUFSIZE= PCMBUFKAYS > 64 ? PCMBUFKAYS : PCMBUFKAYS* 1024;
  616.     SBSIZE= PCMBUFKAYS > 64 ? PCMBUFKAYS/ PCMBUFDIVS : (PCMBUFKAYS/ PCMBUFDIVS)* 1024;
  617.  
  618.     if (!SBSIZE)
  619.         {
  620.         fprintf(stderr, "error: kays: %2d, divs: %2d, size: %5d.\n");
  621.         return(BADOPTION);
  622.         }
  623.  
  624.     if (!OURDMABUF)
  625.         {
  626.         if (USEMONO)
  627.             {
  628.             FP_SEG(OURDMABUF)= 0xB000;
  629.             FP_OFF(OURDMABUF)= 0x0000;
  630.             }
  631.         else 
  632.             {
  633.             if (PCMBUFKAYS > 64)
  634.                 HUGEDMABUF= halloc(2* (long) PCMBUFKAYS, 1);
  635.             else
  636.                 HUGEDMABUF= halloc(2* (long) ((long) ((long) SBSIZE* (long) PCMBUFDIVS)), 1);
  637.             if (!HUGEDMABUF)
  638.                 {
  639.                 fprintf(stderr, "error: can not get huge memory.\n");
  640.                 return(BADPCMBUFFER);
  641.                 }
  642.             if (DEBUG) printf("HugeDMABuf  - %04X:%04X\n", FP_SEG(HUGEDMABUF), FP_OFF(HUGEDMABUF));
  643.  
  644.             if (!(OURDMABUF= doFindDMABuffer(HUGEDMABUF, PCMBUFKAYS)))
  645.                 {
  646.                 if (HUGEDMABUF)
  647.                     hfree(HUGEDMABUF);
  648.                 fprintf(stderr, "error: can not get pcm buffer.\n");
  649.                 return(BADPCMBUFFER);
  650.                 }
  651.             }
  652.         }
  653.     return(OKAY);
  654. }
  655.  
  656. checkforsig()
  657. {
  658.     int status;
  659.  
  660.     _asm
  661.         {
  662.         mov al, 94h
  663. ;        mov ah, GETDOSVECTOR
  664.         mov ah, 35h
  665.         int 21h
  666.  
  667.         xor ax, ax
  668.         dec ax
  669.  
  670.         cmp es:[bx][-9], 'P'
  671.         jnz nodriver
  672.         cmp es:[bx][-8], 'C'
  673.         jnz nodriver
  674.         cmp es:[bx][-7], 'M'
  675.         jnz nodriver
  676.         cmp es:[bx][-6], 'D'
  677.         jnz nodriver
  678.         cmp es:[bx][-5], 'R'
  679.         jnz nodriver
  680.         cmp es:[bx][-4], 'I'
  681.         jnz nodriver
  682.         cmp es:[bx][-3], 'V'
  683.         jnz nodriver
  684.         cmp es:[bx][-2], 'E'
  685.         jnz nodriver
  686.         cmp es:[bx][-1], 'R'
  687.         jnz nodriver
  688.  
  689.         xor ax, ax
  690.  
  691.         nodriver:
  692.  
  693.         mov status, ax
  694.         }
  695.  
  696.     return(status);
  697. }
  698.  
  699. /* initialize sound, return fail, otherwise set PCMPAUSED */
  700.  
  701. struct pcmstate
  702. {
  703.     char far *f00r;
  704.     int f01r;
  705.     long f02c1;
  706.     int f02c2;
  707.     int f02r;
  708.     void (far *f04c)();
  709.     void (far *f04r)();
  710.     char huge *f11c1;
  711.     int f11c2;
  712.     char far *f11r;
  713.     char far *f03c1;
  714.     int f03c2;
  715.     int f03c3;
  716.     char far *f03r;
  717.     int f10r;
  718.     int f05r;
  719.     int f07r;
  720.     int volatile far *stat;
  721.     int fh;
  722.     int sbsize;
  723.     int f02c3;
  724.     int f02c4;
  725. };
  726.  
  727. struct pcmstate ps;
  728.  
  729. setupsound(BT *bt)
  730. {
  731.     int i;
  732.     int lib;
  733.     char far *hwt;
  734.     void (far *cfp)();
  735.     char far *dma;
  736.     void (far *f) ();
  737.     void far dspfilter();
  738.     void far dspmonowav();
  739.     void far dspstereowav();
  740.     void far dsp16monowav();
  741.     void far dsp16stereowav();
  742.  
  743.     if (DOVIDEO)
  744.         if (bt->wf.channels == 1)
  745.             if (bt->wf.datasize == 8)
  746.                 USERFUNC= 1;
  747.             else
  748.             if (bt->wf.datasize == 16)
  749.                 USERFUNC= 3;
  750.             else
  751.                 USERFUNC= 0;
  752.         else
  753.         if (bt->wf.channels == 2)
  754.             if (bt->wf.datasize == 8)
  755.                 USERFUNC= 2;
  756.             else
  757.             if (bt->wf.datasize == 16)
  758.                 USERFUNC= 4;
  759.             else
  760.                 USERFUNC= 0;
  761.         else
  762.             USERFUNC= 0;
  763. /*    else    
  764.         USERFUNC= USERFUNC; 
  765. */
  766.  
  767.     switch (USERFUNC)
  768.         {
  769.         case 0: f= (void far *) 0; break;
  770.         case 1: f= dspmonowav; break;
  771.         case 2: f= dspstereowav; break;
  772.         case 3: f= dsp16monowav; break;
  773.         case 4: f= dsp16stereowav; break;
  774.         default: f= (void far *) 0;
  775.         }
  776.  
  777.     ps.f02c1= bt->wf.samplerate;
  778.     ps.f02c2= bt->wf.channels == 2 ? 1 : 0;
  779.     ps.f02c3= 0;
  780.     ps.f02c4= bt->wf.datasize;
  781.     ps.f03c1= OURDMABUF;
  782.     ps.f03c2= PCMBUFKAYS > 64 ? PCMBUFKAYS: PCMBUFKAYS* 1024;
  783.     ps.f03c3= PCMBUFDIVS;
  784.     ps.f04c= f;
  785.     ps.stat= &OURSTATFLAG;
  786.     ps.fh= bt->fhidx;
  787.  
  788.     _asm
  789.         {
  790.         mov ax, seg ps;
  791.         mov es, ax
  792.         mov bx, offset ps;
  793.         mov si, 08011h
  794.         int 94h
  795.         }
  796.  
  797.     hwt= ps.f00r;
  798.     lib= ps.f01r;
  799.     i= ps.f02r;
  800.     dma= ps.f03r;
  801.     cfp= ps.f04r;
  802.  
  803.     if (!(hwt && lib && i != -1 && dma && cfp))
  804.         {
  805.         return(BADPCMBUFFER);
  806.         }
  807.  
  808.     if (DEBUG)
  809.         {
  810.         printf("%Fp  %5u  %3u  %5u\n", ps.f03c1, ps.f03c2, ps.f03c3, ps.sbsize);
  811.         }
  812.  
  813.     PCMPAUSED= YES;
  814.     return(OKAY);
  815. }
  816.  
  817. static int counter;
  818. donothing()
  819. {
  820.     int c;
  821.  
  822.     if (BEQUIET)
  823.         OURSTATFLAG--;
  824.  
  825.     if ((_bios_keybrd(_KEYBRD_READY)))
  826.         {
  827.         if (DOVIDEO)
  828.             {
  829.             switch ((c= _bios_keybrd(_KEYBRD_READ))& 0xFF)
  830.                 {
  831.                 case 0x00:
  832.                     {
  833.                     switch ((c& 0xFF00)>> 8)
  834.                         {
  835.                         default:
  836.                             ;
  837.                         }
  838.                     }
  839.                     break;
  840.  
  841.                 case '\n': rstpal(); break;
  842.  
  843.                 case 'P':
  844.                     {
  845.                     _asm
  846.                         {
  847.                         push si
  848.                         mov si, 7    ; PausePCM
  849.                         int 94h
  850.                         pop si
  851.                         }
  852.                     switch ((char) _bios_keybrd(_KEYBRD_READ))
  853.                         {
  854.                         case '0': usepal(0); setpal(); break;
  855.                         case '1': usepal(1); setpal(); break;
  856.                         case '2': usepal(2); setpal(); break;
  857.                         case '3': usepal(3); setpal(); break;
  858.                         case '4': usepal(4); setpal(); break;
  859.                         case '5': usepal(5); setpal(); break;
  860.                         case '6': usepal(6); setpal(); break;
  861.                         case '7': usepal(7); setpal(); break;
  862.                         case '8': usepal(8); setpal(); break;
  863.                         }
  864.                     _asm
  865.                         {
  866.                         push si
  867.                         mov si, 8    ; ResumePCM
  868.                         int 94h
  869.                         pop si
  870.                         }
  871.                     }
  872.                     break;
  873.             
  874.                 case 'u': uflppal();        setpal(); break;
  875.                 case 'd': dflppal();        setpal(); break;
  876.                 case 'U':
  877.                     {
  878.                     int i;
  879.                     for (i= 0; i < 10; i++)
  880.                         uflppal();
  881.                     }
  882.                     setpal(); break;
  883.                 case 'D':
  884.                     {
  885.                     int i;
  886.                     for (i= 0; i < 10; i++)
  887.                         dflppal();
  888.                     }
  889.                     setpal(); break;
  890.                 case 'F': f16cycpal();     setpal(); break;
  891.                 case 'f': fcycpal();        setpal(); break;
  892.                 case 'B': b16cycpal();     setpal(); break;
  893.                 case 'b': bcycpal();        setpal(); break;
  894.                 case 'c': CYCLESPEED++;     break;
  895.                 case 'C': CYCLESPEED+= 10;    break;
  896.                 case 'r': CYCLESPEED*= -1;    break;
  897.                 case ' ': CYCLESPEED= 0;     break;
  898.  
  899.                 case 0x1B: return(0x1B);
  900.  
  901.                 }
  902.             }
  903.         else
  904.             switch ((c= _bios_keybrd(_KEYBRD_READ))& 0xFF)
  905.                 {
  906.                 case 0x00:
  907.                     {
  908.                     switch ((c& 0xFF00)>> 8)
  909.                         {
  910.                         default:
  911.                             ;
  912.                         }
  913.                     }
  914.                     break;
  915.  
  916.                 case 0x1B: return(0x1B);
  917.                 }
  918.  
  919.         }
  920.  
  921.     if (DOVIDEO)
  922.         {
  923.         counter++;
  924.         if (CYCLESPEED)
  925.             {
  926.             int c= CYCLESPEED < 0 ? -CYCLESPEED : CYCLESPEED;
  927.             if (!(counter% c))
  928.                 {
  929.                 if (CYCLESPEED < 0)
  930.                     bcycpal();
  931.                 else
  932.                     fcycpal();
  933.                 setpal();
  934.                 }
  935.             }
  936.         }
  937.  
  938.     return(OKAY);
  939.  
  940. }
  941.  
  942. /* set mcga mode, display picture */
  943. #define MAXPICTURES 3
  944. char *pictures[]=
  945. {
  946.     "tpcm.scr",
  947.     "tpcm2.scr",
  948.     "tpcm3.scr"
  949. };
  950.  
  951. initvideo(char *path, int picture)
  952. {
  953.     int i;
  954.     unsigned int idx= 0;
  955.     int inp;
  956.     
  957.     _setvideomode(_MRES256COLOR);
  958.  
  959.     if (picture < 1 || picture > MAXPICTURES)
  960.         picture= 1;
  961.  
  962.         {
  963.         char filename[_MAX_PATH];
  964.         char *f;
  965.         strcpy(filename, path);
  966.         for (f= filename; *f; f++) ;
  967.         for (--f; *f != '\\' && f > filename; f--) ;
  968.         if (*f == '\\') f++;
  969.         strcpy(f, pictures[picture- 1]);
  970.         inp= open(filename, O_BINARY| O_RDONLY);
  971.         }
  972.  
  973.     setpal();
  974.     if (USEPALETTE)
  975.         usepal(USEPALETTE);
  976.     else
  977.     if (DOVIDEO == 2)
  978.         usepal(6);
  979.     else
  980.         usepal(2);
  981.     setpal();
  982.  
  983.     if (inp == ERROR)
  984.         return(OKAY);
  985.  
  986.     for (i= 0; i < 200; i++)
  987.         {
  988.         read(inp, vidbuf, 320);
  989.         if (DOVIDEO == 2)
  990.             if (i >= V2Y && i < V2Y+ V2H+ V2D)
  991.                 {
  992.                 int j;
  993.                 for (j= 0; j < V2W; j++)
  994.                     {
  995.                     v2fun[i- V2Y][j]= vidbuf[V2X+ j];
  996. //                    vidbuf[V2X+ j]= 0;
  997.                     }
  998.                 }
  999.         _asm
  1000.             {
  1001.             push di
  1002.             push si
  1003.             push ds
  1004.             push es
  1005.  
  1006.             mov di, 0A000h
  1007.             mov es, di
  1008.             mov di, idx
  1009.  
  1010.             mov ax, seg vidbuf
  1011.             mov ds, ax
  1012.             mov si, offset vidbuf
  1013.  
  1014.             mov cx, 320
  1015.             rep movsb
  1016.  
  1017.             pop es
  1018.             pop ds
  1019.             pop si
  1020.             pop di
  1021.             }
  1022.         idx+= 320;
  1023.         }
  1024.     close(inp);
  1025.  
  1026.     return(OKAY);
  1027. }
  1028.  
  1029. dspv2fun(unsigned int level)
  1030. {
  1031.     unsigned int i;
  1032.     unsigned int j;
  1033.  
  1034.     if (level > V2D)
  1035.         level= V2D;
  1036.  
  1037.     for (i= 0; i < V2H+ V2D; i++)
  1038.         {
  1039.         unsigned int idx= ((V2Y+ i)* 320)+ V2X;
  1040.         char far *v= &v2fun[i][0];
  1041.  
  1042.         _asm
  1043.             {
  1044.             push si
  1045.             push di
  1046.             push ds
  1047.             mov ax, 0A000h
  1048.             mov es, ax
  1049.             mov di, idx
  1050.  
  1051.             mov ax, word ptr v[2]
  1052.             mov ds, ax
  1053.             mov si, word ptr v[0]
  1054.  
  1055.             mov cx, V2W
  1056.             cld
  1057.             rep movsb
  1058.             pop ds
  1059.             pop di
  1060.             pop si
  1061.             }
  1062.         }
  1063.  
  1064.     for (i= 0; i < level; i++)
  1065.         {
  1066.         unsigned int idx= ((V2Y+ i)* 320)+ V2X+ (2* i);
  1067.         unsigned int j= V2W- (2* i)- i;
  1068.         _asm
  1069.             {
  1070.             push di
  1071.             mov ax, 0A000h
  1072.             mov es, ax
  1073.             mov di, idx
  1074.             mov cx, j
  1075.             xor al, al
  1076.             cld
  1077.             rep stosb
  1078.             pop di
  1079.             }
  1080.         }
  1081.  
  1082.     for (i= 0; i < V2H- (level/ 2); i++)
  1083.         {
  1084.         unsigned int idx= ((V2Y+ i+ level)* 320)+ V2X+ (2* i);
  1085.         unsigned int j= V2W- (2* i)- i;
  1086.         char far *v= &v2fun[i][(2* i)];
  1087.  
  1088.         _asm
  1089.             {
  1090.             push si
  1091.             push di
  1092.             push ds
  1093.             mov ax, 0A000h
  1094.             mov es, ax
  1095.             mov di, idx
  1096.  
  1097.             mov ax, word ptr v[2]
  1098.             mov ds, ax
  1099.             mov si, word ptr v[0]
  1100.  
  1101.             mov cx, j
  1102.             cld
  1103.             rep movsb
  1104.             pop ds
  1105.             pop di
  1106.             pop si
  1107.             }
  1108.         }
  1109.  
  1110. }
  1111.  
  1112. calcenergylevel(char far *buf, unsigned int size, BT *bt)
  1113. {
  1114.     int retval;
  1115.  
  1116.     if (bt->wf.datasize == 8)
  1117.         {
  1118.         char far *b= buf;
  1119.         unsigned int s= size;
  1120.         unsigned int level= 0;
  1121.  
  1122.         for (s= 0; s < size; s++, b++)
  1123.             {
  1124.             char c= *b^ 0x80;
  1125.             int x= c;
  1126.             level+= x* x;
  1127.             }
  1128.  
  1129.         retval= level& 0x7FFF;
  1130.         }
  1131.     else
  1132.     if (bt->wf.datasize == 16)
  1133.         {
  1134.         int far *b= (int far *) buf;
  1135.         unsigned int s= size;
  1136.         unsigned long level= 0;
  1137.  
  1138.         for (s= 0; s < size; s++, b++)
  1139.             {
  1140.             int x= *b;
  1141.             level+= x* x;
  1142.             }
  1143.  
  1144.         retval= level>> 8;
  1145.         retval&= 0x7FFF;
  1146.         }
  1147.  
  1148.     return(retval/ (1<< (16- V2D)));
  1149. }
  1150.  
  1151. char buf[20];
  1152. char far *bufptr= buf;
  1153.  
  1154. char far *doFindDMABuffer(char huge *hbuf, uint pcmbufsize)
  1155. {
  1156.     char far *retval;
  1157.     uint bufoff= FP_OFF(bufptr);
  1158.     uint bufseg= FP_SEG(bufptr);
  1159.     char huge **chb= (char huge *) buf;
  1160.  
  1161.     *chb= hbuf;
  1162.     buf[4]= (uint) pcmbufsize;
  1163.  
  1164.      _asm
  1165.         {
  1166.         push si
  1167.         mov ax, bufseg
  1168.         mov es, ax
  1169.         mov bx, bufoff
  1170.         mov si, 11
  1171.         int 94h
  1172.         pop si
  1173.         mov word ptr retval[0], ax
  1174.         mov word ptr retval[2], dx
  1175.         }
  1176.     return(retval);
  1177. }
  1178.  
  1179.