home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 17 / CD_ASCQ_17_101194.iso / dos / prg / demosrce / headache / sb_dma.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1994-08-01  |  9.0 KB  |  305 lines

  1. {///////////////////////////////////////////////////////////////////////////}
  2. { Ca y est...  je  me suis  décidé  à mettre  le source  de HEADACHE dans le
  3.   domaine public!  A mon point  de vue,  c'est  un petit programme assez peu
  4.   important,  mais c'est a priori  susceptible  d' intéresser  quelques  uns
  5.   d'entre vous.  Ceux-ci  sont  évidemment  curieux  de savoir  comment "ça"
  6.   marche! En fait, c'est relativement simple (une fois  que l'on a visualisé
  7.   le fichier PCX), sauf peut-être en ce qui concerne  la partie graphique en
  8.   BASM.  J'ai fait un effort violent  en réécrivant  les routines SB pour le
  9.   DMA  entièrement  en TP (à l'origine c'est en BASM et pour toute ligne IRQ
  10.   et canal DMA,  et avec  une réelle détection automatique du port). Voilà!,
  11.   sachez donc tirer profit  de ce petit cadeau  et évitez de faire partie du
  12.   club  très large  des  LAMERS  en "pompant"  bêtement  et en changeant les
  13.   textes des messages...
  14.  
  15.   ATTENTION!  le numéro de téléphone  dans la démo  n'est plus valable!!!...
  16.   Pour  de  plus  amples  informations,  d'éventuelles suggestions,  ou tout
  17.   simplement pour le fun, vous pouvez m'écrire à l'adresse suivante:
  18.  
  19.                                Patrick Ruelle
  20.                          43, av. de Grande Bretagne
  21.                                 98000 Monaco
  22.                             Principauté de Monaco
  23.  
  24.   Evidemment  je n'ai pas pris  la décision  de diffuser  ce source  dans le
  25.   but de demander de l'argent,  mais il va de soit que toutes sortes de dons
  26.   sont acceptés (carte  postale,  matos,  argent, spécialités locales, docs,
  27.   etc...).  N'oubliez pas non plus que cette diffusion ne m'enlève nullement
  28.   mes  droits d'auteur  de cette mmm... de démo;  ce petit package peut être
  29.   diffusé librement à condition de rester sous sa forme initiale:
  30.  
  31.  HEADACHE.EXE  01/08/94  13264 L'exécutable utilisant HEADIMG et les HEADSEQ
  32.  HEADACHE.PAS  01/08/94  17253 Le source principal de la démo
  33.  SB_DMA  .PAS  01/08/94   9170 Le source des routines DMA pour la SB
  34.  HEADACHE.PCX  25/04/93   8471 L'image des sprites au format PCX
  35.  HEADIMG .RAW  25/07/94  64768    "     "     "    en format brut (img+pal)
  36.  HEADSEQ .1    25/07/94  20040 Le 1er pattern digital de musique
  37.  HEADSEQ .2    25/07/94  20168  " 2e     "       "     "    "
  38.  HEADSEQ .3    25/07/94  20040  " 3e     "       "     "    "
  39.  HEADSEQ .4    25/07/94  20168  " 4e     "       "     "    "
  40.  HEADSEQ .5    25/07/94  20168  " 5e     "       "     "    "
  41.  HEADSEQ .6    25/07/94  20168  " 6e     "       "     "    "
  42.  HEADSEQ .7    25/07/94  20104  " 7e     "       "     "    "
  43.                         ------
  44.                TOTAL    253782
  45.  
  46.   La version  actuelle  est remaniée exprès pour la diffusion de ce package,
  47.   mais en fait ce programme date de début 1993...
  48.  
  49.                                           Patrick Ruelle (Monac) / GRYPHAEA }
  50. {///////////////////////////////////////////////////////////////////////////}
  51. UNIT SB_DMA; {Uniquement pour IRQ=7 et DMA=1,  mais facilement adaptable}
  52.              {pour un autre IRQ et DMA. La détection automatique du port}
  53.              {de base se fait en testant les Dizaines avec InitDSP.     }
  54. INTERFACE
  55.  
  56.  
  57. VAR
  58.  s            :ARRAY[1..7] OF Pointer;
  59.  sequence     :BYTE;
  60.  sounds       :Pointer;
  61.  snd,sze,sizes:WORD;
  62.  
  63.  
  64. FUNCTION  InitDSP(base:WORD):BOOLEAN;
  65. PROCEDURE SpeakerON;
  66. PROCEDURE SpeakerOFF;
  67. PROCEDURE ArreteDMA;
  68. PROCEDURE InitPlayback(son:Pointer; taille:WORD; frequence:WORD);
  69. PROCEDURE FinPlayBack;
  70.  
  71.  
  72. IMPLEMENTATION
  73.  
  74.  
  75. USES Crt,Dos;
  76.  
  77.  
  78. VAR
  79.  DSP_RESET,DSP_READ_DATA,
  80.  DSP_WRITE_DATA,
  81.  DSP_WRITE_STATUS,
  82.  DSP_DATA_AVAIL,i,Offse  :WORD;
  83.  OldIRQ                  :Pointer;
  84.  Page                    :BYTE;
  85.  
  86.  
  87. FUNCTION InitDSP(base:WORD):BOOLEAN; {1<=base<=6 correspond à 210h à 260h}
  88. BEGIN
  89.   base:=base*$10;
  90.   {Calculs des adresses utiles}
  91.   DSP_RESET       :=base+$206;
  92.   DSP_READ_DATA   :=base+$20A;
  93.   DSP_WRITE_DATA  :=base+$20C;
  94.   DSP_WRITE_STATUS:=base+$20C;
  95.   DSP_DATA_AVAIL  :=base+$20E;
  96.   {Reinitialise le DSP}
  97.   Port[DSP_RESET]:=1;
  98.   Delay(30);
  99.   Port[DSP_RESET]:=0;
  100.   Delay(30);
  101.   IF (Port[DSP_DATA_AVAIL] AND $80=$80) AND (Port[DSP_READ_DATA]=$AA) THEN
  102.     InitDSP:=True
  103.   ELSE
  104.     InitDSP:=False;
  105. END;
  106.  
  107.  
  108. PROCEDURE EcritDSP(valeur:BYTE);
  109. BEGIN
  110.   WHILE Port[DSP_WRITE_STATUS] AND $80<>0 DO;
  111.   Port[DSP_WRITE_DATA]:=valeur;
  112. END;
  113.  
  114.  
  115. FUNCTION LitDSP:BYTE;
  116. BEGIN
  117.   WHILE Port[DSP_DATA_AVAIL] AND $80=0 DO;
  118.   LitDSP:=Port[DSP_READ_DATA];
  119. END;
  120.  
  121.  
  122. PROCEDURE EcritDAC(Commande:BYTE);
  123. BEGIN
  124.   EcritDSP($10);
  125.   EcritDSP(Commande);
  126. END;
  127.  
  128.  
  129. FUNCTION LitDAC:BYTE;
  130. BEGIN
  131.   EcritDSP($20);
  132.   LitDAC:=LitDSP;
  133. END;
  134.  
  135.  
  136. PROCEDURE SpeakerON;
  137. BEGIN
  138.   EcritDSP($D1);
  139. END;
  140.  
  141.  
  142. PROCEDURE SpeakerOFF;
  143. BEGIN
  144.   EcritDSP($D3);
  145. END;
  146.  
  147.  
  148. PROCEDURE ArreteDMA;
  149. BEGIN
  150.   EcritDSP($D0);
  151. END;
  152.  
  153.  
  154. PROCEDURE Playback;INTERRUPT; {Routine greffée sur l'IRQ déclenchée par le}
  155. VAR                           {DSP de la carte SoundBlaster en fin de DMA }
  156.     recu       :BYTE;
  157. BEGIN
  158.   {Accusé de réception}
  159.   recu:=Port[DSP_DATA_AVAIL];
  160.   {Calcul de l'adresse Physique et Page de la sequence}
  161.   offse :=Seg(sounds^) SHL 4+Ofs(sounds^);
  162.   page  :=(Seg(sounds^)+Ofs(sounds^) SHR 4) SHR 12;
  163.   {Préparation du DMAC pour le transfert}
  164.   Port[$0A]:=5;         {5=4+CanalDMA; donc 7=DMA3}
  165.   Port[$0C]:=0;
  166.   Port[$0B]:=$49;       {Via DAC}
  167.   Port[$02]:=Lo(offse );{06 pour DMA3}
  168.   Port[$02]:=Hi(offse );{06 pour DMA3}
  169.   Port[$83]:=page;
  170.   Port[$03]:=Lo(sizes); {07 pour DMA3}
  171.   Port[$03]:=Hi(sizes); {07 pour DMA3}
  172.   Port[$0A]:=1;         {Canal DMA}
  173.   {Activation du transfert par le DAC}
  174.   EcritDSP($14);
  175.   EcritDSP(Lo(sizes));
  176.   EcritDSP(Hi(sizes));
  177.   {Actualisation de la séquence à jouer; ici on est en tâche de fond}
  178.   {Le morceau est constitué d'un assemblage de 44 patterns parmi 7, }
  179.   {pour une durée approximative  de 1mn20s à 11KHz.  Le bouclage est}
  180.   {effectif après le 44e pattern                                    }
  181.   Inc(sequence);
  182.   IF sequence>44 THEN sequence:=1;
  183.   CASE sequence OF
  184.    1..4                       :BEGIN
  185.                                  Snd:=1;
  186.                                  Sze:=19976-1;
  187.                                END;
  188.    8,13..15,17..19,30,32,38,40:BEGIN
  189.                                  Snd:=2;
  190.                                  Sze :=20104-1;
  191.                                END;
  192.    5..7,9..11,41              :BEGIN
  193.                                  Snd:=3;
  194.                                  Sze :=19976-1;
  195.                                END;
  196.    12,16,20,33..36,42..44     :BEGIN
  197.                                  Snd:=4;
  198.                                  Sze :=20104-1;
  199.                                END;
  200.    21..23,25..27,29,37        :BEGIN
  201.                                  Snd:=5;
  202.                                  Sze :=20104-1;
  203.                                END;
  204.    24                         :BEGIN
  205.                                  Snd:=6;
  206.                                  Sze :=20104-1;
  207.                                END;
  208.    28,31,39                   :BEGIN
  209.                                  Snd:=7;
  210.                                  Sze :=20040-1;
  211.                                END;
  212.   END;
  213.   sounds:=s[snd];
  214.   sizes :=sze;          {à ce niveau la taille est déja ajustée à -1}
  215.   {Avis de fin d'interruption au contrôleur d'INT}
  216.   Port[$20]:=$20;
  217. END;
  218.  
  219.  
  220. PROCEDURE ActiveIRQ(i:WORD);
  221. BEGIN
  222.   IF i<8 THEN
  223.     PORT[$21]:=PORT[$21] AND (NOT (1 SHL i))
  224.   ELSE
  225.   BEGIN
  226.     PORT[$A1]:=PORT[$A1] AND (NOT (1 SHL (i-8)));
  227.     PORT[$21]:=PORT[$21] AND (NOT (1 SHL 2));
  228.   END;
  229. END;
  230.  
  231.  
  232. PROCEDURE DesactiveIRQ(i:WORD);
  233. BEGIN
  234.   IF i<8 THEN
  235.     PORT[$21]:=PORT[$21] OR (1 SHL i)
  236.   ELSE
  237.   BEGIN
  238.     PORT[$A1]:=PORT[$A1] OR (1 SHL (i-8))
  239.   END;
  240. END;
  241.  
  242.  
  243. FUNCTION ChangeVecteurIRQ(i:WORD; Vec:POINTER):POINTER;
  244. VAR
  245.  p:POINTER;
  246.  j:WORD;
  247. BEGIN
  248.   IF i<8 THEN
  249.     j:=i+$08
  250.   ELSE
  251.     j:=i+$68;
  252.   GetIntVec(j,p);
  253.   SetIntVec(j,Vec);
  254.   ChangeVecteurIRQ:=p;
  255. END;
  256.  
  257.  
  258. PROCEDURE InitPlayback(son:Pointer; taille:WORD; frequence:WORD);
  259. VAR time_constant:WORD;
  260. BEGIN
  261.   {Définit la fréquence}
  262.   time_constant:=256-1000000 DIV frequence;
  263.   EcritDSP($40);
  264.   EcritDSP(time_constant);
  265.   SpeakerON;
  266.   taille:=taille-1;
  267.   sounds:=son;
  268.   offse :=Seg(sounds^) SHL 4+Ofs(sounds^);
  269.   page  :=(Seg(sounds^)+Ofs(sounds^) SHR 4) SHR 12;
  270.   Port[$0A]:=5;
  271.   Port[$0C]:=0;
  272.   Port[$0B]:=$49;
  273.   Port[$02]:=Lo(offse);
  274.   Port[$02]:=Hi(offse);
  275.   Port[$83]:=page;
  276.   Port[$03]:=Lo(taille);
  277.   Port[$03]:=Hi(taille);
  278.   Port[$0A]:=1;
  279.   {La routine PlayBack est sur l'IRQ 7}
  280.   OldIRQ:=ChangeVecteurIRQ(7,@PlayBack);
  281.   ActiveIRQ(7);
  282.   EcritDSP($14);
  283.   EcritDSP(Lo(taille));
  284.   EcritDSP(Hi(taille));
  285.   {Préparation pour la sequence suivante (jouée alors par la routine IRQ)}
  286.   Sequence:=2;
  287.   snd:=1;
  288.   sze:=19976-1;
  289.   sounds:=s[snd];
  290.   sizes :=sze;          {à ce niveau la taille est déja ajustée à -1}
  291. END;
  292.  
  293.  
  294. PROCEDURE FinPlayBack;
  295. VAR p:Pointer;
  296. BEGIN
  297.   ArreteDMA;
  298.   DesactiveIRQ(7);
  299.   p:=ChangeVecteurIRQ(7,OldIRQ);
  300.   SpeakerOFF;
  301. END;
  302.  
  303.  
  304. END.
  305.