home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser 2002 January / STC_CD_01_2002.iso / APP / TRAIL_PG / GEMJING / GEMJ136.LZH / Develop / JINGLE.C < prev    next >
C/C++ Source or Header  |  2000-05-25  |  24KB  |  1,009 lines

  1. /* JINGLE */
  2. /* hardwarenahes Modul ohne Oberflächenfunktionalität für GEMJing */
  3. /* (c) und alle Rechte bei Götz Hoffart, Rheinstetten */
  4.  
  5. #define NDEBUG 1
  6. #include <tos.h>
  7. #include <assert.h>
  8. #include <portabn.h>
  9. #include <string.h>
  10. #include <aes.h>
  11. #include <stdio.h>
  12. #include <ext.h>
  13.  
  14. #include "jinglein.h"
  15.  
  16. #include "error.h"
  17. #include "SAMROUTS\samrouts.h"
  18. #include "snd.h"
  19. #include "jingle.h"
  20. #include "data.h"
  21.  
  22. #define Macintosh 1
  23. #define Falcon        2
  24. #define WeirdMac    3
  25.  
  26. BOOLEAN totalbreak;
  27. BOOLEAN sample_interrupt = FALSE;
  28. extern BOOLEAN quit;
  29.  
  30. extern BOOLEAN    MultiTOS;
  31. extern BOOLEAN    MagiC;
  32. extern BOOLEAN    MagiCMac;
  33.  
  34.  
  35. LOCAL VOID        flip_word (REG BYTE *adr);
  36. LOCAL VOID        flip_long (REG WORD *adr);
  37. LOCAL WORD        main(VOID);
  38. LOCAL WORD        flc_play_sam(NEWDEF *new);
  39. LOCAL LONG        FileLen(CONST BYTE *fname);
  40. LOCAL BOOLEAN    IsThereMxalloc(VOID);
  41. LOCAL VOID        *OwnMalloc(CONST LONG amount, CONST WORD typ);
  42. LOCAL VOID        OwnMfree(CONST VOID *adr);
  43. LOCAL BOOLEAN    Laden(CONST BYTE *fname, BYTE *addr, CONST LONG len);
  44.  
  45. /* Import aus 16to8.c: */
  46. unsigned char *to_eight(unsigned char *start,unsigned char *end,int unsign);
  47.  
  48. LOCAL WORD    recognize_format(NEWDEF *new, LONG *adr, LONG len);
  49. LOCAL WORD    detect_hardware(NEWDEF *new);
  50. LOCAL WORD    play_sample(NEWDEF *new);
  51. LOCAL LONG    get_cookiejar(VOID);
  52. LOCAL    VOID    warte(NEWDEF *new);
  53. LOCAL WORD    convert_alaw_linear(NEWDEF* new);
  54. LOCAL WORD    convert_mulaw_linear(NEWDEF *new);
  55.  
  56. /************************************************************************/
  57.  
  58. WORD spiele_sample(NEWDEF *new)
  59. {
  60.     BOOLEAN ret;
  61.     WORD spiele_ret;
  62.     LONG len;
  63.     LONG *adr;
  64.  
  65.     sample_interrupt = FALSE;
  66.  
  67.     ret = detect_hardware(new);
  68.     if (ret != TRUE)
  69.         return RT_WRONG_HARDWARE;
  70.     
  71.     if (new->file)
  72.     {
  73.         len = FileLen(new->file);
  74.         adr = OwnMalloc(len, MLC_ST_RAM);
  75.     
  76.         if (len == 0)
  77.             return RT_NO_FILE;
  78.         if (adr == NULL)
  79.             return RT_NO_MEM;
  80.     
  81.         if (Laden(new->file, (BYTE*) adr, len) != TRUE)
  82.         {
  83.             OwnMfree(adr);
  84.             return RT_NO_FILE;
  85.         }
  86.     }
  87.     else if (new->memoryplay != NULL)
  88.     {
  89.         adr = (LONG *) new->memoryplay;
  90.         len = new->memoryplay_len;
  91.     }
  92.     else
  93.         return RT_NO_FILE;
  94.  
  95.     ret = recognize_format(new, adr, len);
  96.     if (ret != TRUE)
  97.     {
  98.         if (new->memoryplay == NULL)
  99.             OwnMfree(adr);
  100.         return ret;
  101.     }
  102.  
  103.     totalbreak = FALSE;
  104. /* x mal wiederholen mit y Sekunden Pause dazwischen */
  105.     while (0==0)
  106.     {
  107.         spiele_ret = play_sample(new);
  108.         new->repeatrate--;
  109.         if (new->repeatrate == 0)
  110.             break;
  111.         if (totalbreak == TRUE)
  112.             break;
  113.         warte(new);
  114.     }
  115.  
  116.     if (new->memoryplay == NULL)
  117.         OwnMfree(adr);    
  118.     return spiele_ret;
  119. }
  120.  
  121. /************************************************************************/
  122.  
  123. /* Dank an Julian Reschke für den Tip mit Fselect() */
  124. /* Etwas modifiziert auf GEMJing-Bedürfnisse */
  125. VOID warte(NEWDEF *new)
  126. {
  127.     WORD seconds = new->delayrate;
  128.  
  129.     while (seconds)
  130.     {
  131.         if (new->no_menu == FALSE)
  132.             evnt_timer(1000, 0);
  133.         else if (Fselect (1000, NULL, NULL, 0L) == EINVFN)
  134.             sleep(1);
  135.         if (Kbshift(-1) == 4+2)
  136.             totalbreak = TRUE;
  137.  
  138.         seconds--;
  139.     }
  140.  
  141.     return;
  142. }
  143.  
  144. /************************************************************************/
  145.  
  146. LOCAL WORD    detect_hardware(NEWDEF *new)
  147. {
  148.     LONG keks;
  149.     LONG dummy;
  150.     McSnCookie_STRCT *mcsn;
  151.  
  152.     /* Bit     0: GI Sound Chip (PSG)
  153.      *         1: DMA 8-Bit
  154.      *            2:    DMA record (XBIOS)
  155.      *            3: 16-Bit CODEC
  156.      *            4: DSP
  157.      */
  158.  
  159.     new->snd_system = NONE_COMP;
  160.  
  161.     if (!get_cookie(_SND_COOKIE, &keks))
  162.         keks = 0;
  163.  
  164.     if (get_cookie(strk_COOKIE, &dummy) == TRUE)
  165.     {
  166.         WORD ret;
  167.  
  168.         ret = (WORD) cardmagic();
  169.         if (ret & 0x6)
  170.         {
  171.             new->snd_system = ST_H_COMP;
  172.         }
  173.         else
  174.         {
  175.             new->snd_system = ST_W_COMP;
  176.         }
  177.     }
  178.     else if ( (soundcmd(7,-1) >= 0) && (get_cookie(HSN_COOKIE, (LONG*) &dummy) == TRUE) )
  179.     {
  180.         if ((get_cookie(McSn_COOKIE, (LONG*) &mcsn) == TRUE) /* && (get_cookie(Lity_COOKIE, &dummy) == FALSE)*/)
  181.             if (mcsn->vers == 1)
  182.                 new->snd_system = HSND_COMP;
  183.     } else if ( (soundcmd(7,-1) >= 0) && (get_cookie(MgPC_COOKIE, (LONG*) &dummy) == TRUE) )
  184.     {
  185.         new->snd_system = HSND_COMP;
  186.     } else if ( (get_cookie(McSn_COOKIE, (LONG*) &mcsn) == TRUE) /*&& (get_cookie(Lity_COOKIE, &dummy) == FALSE*/)
  187.     {
  188.         if (mcsn->vers >= 256)        /* 0x10 lt. Doku */
  189.             new->snd_system = MSND_COMP;
  190.         else if (get_cookie(HSN_COOKIE, &dummy) == TRUE)
  191.             new->snd_system = MSND_COMP;
  192.     }
  193.     else if ( keks >= 8+4 )
  194.         new->snd_system = F030_COMP;
  195.     else if ( keks >= 2 )
  196.         new->snd_system = STE_COMP;
  197.     else if ( (keks >= 1) || (!get_cookie(_SND_COOKIE, &keks)) ) /* Kein Soundcookie gefunden? */
  198.         new->snd_system = ST_COMP; /* dann mu₧ es ein ST sein */
  199.     else
  200.         return RT_WRONG_HARDWARE;
  201.  
  202.     return TRUE;
  203. }
  204.  
  205. /************************************************************************/
  206.  
  207. LOCAL WORD    recognize_format(NEWDEF *new, LONG *adr, LONG len)
  208. {
  209.     LONG *fmt_tag;
  210.     LONG *end = (LONG*) ((LONG)adr + len);
  211.  
  212.     /* Format feststellen und in ein signed-Sample mit der new-Struktur */
  213.     /* wandeln */
  214.  
  215.     fmt_tag = (LONG *) adr;
  216.  
  217.     if (*fmt_tag == DVS_HEAD)        /* wenn Quellformat == DVS-Format */
  218.     {
  219.         DVSMHEAD *dvs;
  220.  
  221.         dvs = (DVSMHEAD *) adr;
  222.  
  223.         new->fmt = 2;
  224.         new->adr = (WORD *)adr;
  225.         new->end = (WORD *)((LONG)adr + len);
  226.         new->len = len - dvs->headlen;
  227.  
  228.         new->sample_start = (WORD *)((LONG) new->adr + dvs->headlen);
  229.  
  230.         if (dvs->pack != 0)
  231.         {
  232.             OwnMfree(new->adr);
  233.             return(RT_PACKED);
  234.         }
  235.  
  236.         switch(dvs->freq)
  237.         {
  238.             case DVS8    :    new->frq = 8195L; break;
  239.             case DVS9    :    new->frq = 9833L; break;
  240.             case DVS12    :    new->frq = 12292L; break;
  241.             case DVS16    :    new->frq = 16390L; break;
  242.             case DVS19    :    new->frq = 19668L; break;
  243.             case DVS24    :    new->frq = 24585L; break;
  244.             case DVS32    :    new->frq = 32780L; break;
  245.             case DVS49    :    new->frq = 49170L; break;
  246.             default        :    new->frq = 24585L; 
  247.         }
  248.  
  249.         new->res = 8;
  250.         new->channels = 2;
  251.         switch (dvs->mode)
  252.         {
  253. /*            case 0: break;*/
  254.             case 1: new->res = 16; break;
  255.             case 2: new->channels = 1; break;
  256.         }
  257.     }
  258.     else 
  259.     if (*fmt_tag == WAV_HEAD)        /* wenn Quellformat == WAV-Format ('RIFF')*/
  260.     {
  261.         LONG *pl = adr;
  262.         SUB_CH *sub_ch;
  263.         LONG data_length;
  264.  
  265.         pl++;
  266.         flip_long((WORD *) pl);
  267.         new->len = *pl;
  268.  
  269.         while (*pl != 'WAVE')
  270.         {
  271.             if (pl >= end)
  272.                 return RT_WRONG_FILE;
  273.             pl++;
  274.         }
  275.  
  276.     /* XXX Problem: Tag mu₧ nicht an LONG-aligned Adresse liegen! */
  277.         while (*pl != 'fmt ')
  278.         {
  279.             if (pl >= end)
  280.                 return RT_WRONG_FILE;
  281.             pl++;
  282.         }
  283.  
  284.         if (*pl == 'fmt ')
  285.             pl++;
  286.  
  287.         sub_ch = (SUB_CH*) pl;
  288.  
  289.         flip_long((WORD *) &sub_ch->len_sub);
  290.         flip_word((BYTE *) &sub_ch->format);
  291.         flip_word((BYTE *) &sub_ch->modus);
  292.         flip_long((WORD *) &sub_ch->sample_fq);
  293.         flip_long((WORD *) &sub_ch->byte_p_sec);
  294.         flip_word((BYTE *) &sub_ch->byte_p_spl);
  295.         flip_word((BYTE *) &sub_ch->bit_p_spl);
  296.  
  297.         /* "vorspulen" */
  298.         while (*pl != 'data')
  299.         {
  300.             if (pl >= end)
  301.                 return RT_WRONG_FILE;
  302.             pl++;
  303.         }
  304.  
  305.         pl++;
  306.         new->header_len = (LONG) pl - (LONG) adr;
  307.         flip_long((WORD *) pl);
  308.         data_length = *pl;
  309.         if (data_length > (new->len - new->header_len))
  310.             data_length = new->len - new->header_len;
  311.  
  312.         new->sample_start = (WORD*) ++pl;
  313.  
  314.         new->fmt = 1;
  315.         new->adr = (WORD *) adr;
  316.  
  317.         /* einige Windows-WAVs korrigieren */
  318.         if(sub_ch->len_sub<=1 || sub_ch->len_sub>=256)
  319.             sub_ch->len_sub=16;
  320.  
  321.         new->end = (WORD *)((LONG)new->sample_start + data_length);
  322.  
  323.         convert8_sam((BYTE *)new->sample_start, data_length);
  324.         new->frq = sub_ch->sample_fq;
  325.         new->res = sub_ch->bit_p_spl;
  326.         new->channels = sub_ch->modus;
  327.     }
  328.     else 
  329.     if (*fmt_tag == JAVA_HEAD)        /* wenn Quellformat == Java-Format ('RIFF')*/
  330.     {
  331.         /* Texel-Spezialformat: Java Byte-Code */
  332.         my_java_hd *wav;
  333.  
  334.         wav = (my_java_hd *) adr;
  335.         flip_long((WORD *) &wav->length);
  336.         flip_long((WORD *) &wav->len_sub);
  337.         flip_word((BYTE *) &wav->format);
  338.         flip_word((BYTE *) &wav->modus);
  339.         flip_long((WORD *) &wav->sample_fq);
  340.         flip_long((WORD *) &wav->byte_p_sec);
  341.         flip_word((BYTE *) &wav->byte_p_spl);
  342.         flip_word((BYTE *) &wav->bit_p_spl);
  343.         flip_long((WORD *) &wav->data_length);
  344.         new->fmt = 1;
  345.         new->adr = (WORD *) adr;
  346.         new->len = wav->length;
  347.         if (new->len > len)
  348.             new->len = len;
  349.  
  350.         new->header_len = sizeof(my_wav_hd);
  351.  
  352.         if (wav->data_length > (new->len - new->header_len))
  353.             wav->data_length = new->len - new->header_len;
  354.         
  355.         if ((wav->chunk_type != 0x4A415641L) || (wav->len_sub != 16))
  356.         {
  357.             if (new->memoryplay == NULL)
  358.                 OwnMfree(adr);
  359.             return(RT_WRONG_CHUNK);
  360.         }
  361.  
  362.         new->sample_start = (WORD *)((LONG)new->adr + new->header_len);
  363.         new->end = (WORD *)((LONG)new->sample_start + wav->data_length);
  364.         convert8_sam((BYTE *)new->sample_start, wav->data_length);
  365.         new->frq = wav->sample_fq;
  366.         new->res = wav->bit_p_spl;
  367.         new->channels = wav->modus;
  368.     }
  369.     else if (*fmt_tag == SMP_HEAD)        /* SMP '~ü~ü' (Galactic) */
  370.     {
  371.         SMPHEADER *smp;
  372.         
  373.         smp = (SMPHEADER *) adr;
  374.  
  375.         new->sample_start = (WORD *) ((LONG) adr + smp->header_len);
  376.         new->adr = (WORD *) adr;
  377.         new->end = (WORD *)((LONG)new->adr + smp->sam_len);
  378.         new->len = smp->sam_len;
  379.         new->header_len = smp->header_len;
  380.         new->fmt = 3;
  381.  
  382.         if (new->len > len)                        /* Wenn Samplelänge grö₧er Dateilänge */
  383.             new->len = len - smp->header_len;
  384.  
  385.         new->res = (WORD) smp->res;
  386.         if (new->res != 8)
  387.         {
  388.             if (new->memoryplay == NULL)
  389.                 OwnMfree(adr);
  390.             return RT_WRONG_FILE;
  391.         }
  392.         new->frq = smp->frq;
  393.         new->channels = (smp->flags & 0xff) /*+ 1*/;        /* XXX? Thorsten Ottos Samples gingen nur so*/
  394.     }
  395.     else if (*fmt_tag == STEue_HEAD)        /* SMP 'STEü' (STE-Play) */
  396.     {
  397.         SMPHEADER *smp;
  398.  
  399.         smp = (SMPHEADER *) adr;
  400.  
  401.         new->sample_start = (WORD *) ((LONG) adr + sizeof(SMPHEADER));
  402.         new->adr = (WORD *) adr;
  403.         new->end = (WORD *) ((LONG) new->sample_start + len);
  404.         new->len = smp->sam_len;                /* XXX unbedingt prüfen wg. inkonsistenter Längen (auch Header!) */
  405.         new->res = smp->res;
  406.         if (new->res > 8)
  407.             new->res = 16;
  408.         new->frq = smp->frq;
  409.         new->channels = (smp->flags & 0xff) /*+ 1*/;  /* XXX? */
  410.     }
  411.     else if (*fmt_tag == 'HSND')
  412.     {
  413.         HSN_ALT *hsn;
  414.         WORD offset=0;
  415.         BYTE *dum = (BYTE *) adr;
  416.  
  417.         hsn = (HSN_ALT*) adr;
  418.         new->adr = (WORD *) ((LONG) hsn + sizeof(HSN_ALT));
  419.  
  420.         dum += 6;            /* |HSND1.1  ->  HSND1.|1; | = Pointer */
  421.         if (*dum == '1')    /* neues Format hat 42 Bytes grö₧ere Header */
  422.             offset = 42;
  423.  
  424.         new->end = (WORD *) ((LONG) hsn + hsn->laenge);
  425.         new->sample_start = (WORD *)((LONG) hsn + sizeof(HSN_ALT) + offset);
  426.         new->len = hsn->laenge;
  427.         new->frq = hsn->frequenz * 10;
  428.         new->channels = 1;
  429.         if (hsn->stereo == TRUE)
  430.             new->channels = 2;
  431.  
  432.         new->res = hsn->bitsps;
  433.     }
  434.     else if (*fmt_tag == AVR_HEAD)            /* Michtrons AVR-Format */
  435.     {
  436.         AVR_NEWHEADER *avr;
  437.         BYTE *dum = (BYTE *) adr;
  438.  
  439.         avr = (AVR_NEWHEADER *) adr;
  440.  
  441.         new->adr = (WORD *) adr;
  442.         new->end = (WORD *) ((LONG) adr + len);
  443.         new->sample_start = (WORD *) ((LONG)adr + sizeof(AVR_NEWHEADER));
  444.         new->len = avr->size;
  445.  
  446.         new->res = avr->rez;
  447.         if (new->res > 8)
  448.         {
  449.             new->res = 16;
  450.             new->len = new->len << 1;    /* Länge verdoppeln, da 16 Bit */
  451.         }
  452.         else
  453.             new->res = 8;
  454.  
  455.         new->channels = 1;
  456.         if (avr->mono > 0)        /* 0xffff = stereo */
  457.         {
  458.             new->channels = 2;
  459.         }
  460.  
  461.         if (avr->sign == 0)                /* 0 = unsigned */
  462.         {
  463.             if (new->channels == 1)
  464.                 convert8_sam((BYTE *) new->sample_start, new->len);
  465.             else
  466.                 convert16_sam((BYTE *)new->sample_start, new->len);
  467.         }
  468.  
  469. /* höchstes Byte mit 0 überschreiben, da Intel 3-Byte-Zahl */
  470.         dum = (BYTE*) &(avr->rate);
  471.         dum[0] = 0;        
  472.         new->frq = avr->rate;
  473.         if (new->frq < 1000 || new->frq > 60000L)
  474.             new->frq = 11025;
  475.     }
  476.     else if (*fmt_tag == PSION_HEAD)        /* Psion WVE-Format */
  477.     {
  478.         PSION_WVE_HEADER *psion;
  479.  
  480.         if (strcmp((BYTE*)adr, PSION_COMPLETE_MAGIC) != 0)
  481.             return RT_WRONG_FILE;
  482.  
  483.         psion = (PSION_WVE_HEADER*) adr;
  484.         new->sample_start = (WORD*)((LONG)adr + PSION_HEADER_LEN);
  485.         new->adr = (WORD*) adr;
  486.         if (psion->num_samples < (len - PSION_HEADER_LEN))
  487.             new->len = psion->num_samples;
  488.         else
  489.             new->len = len - PSION_HEADER_LEN;
  490.         new->end = (WORD*) ((LONG)adr + len);
  491.         new->frq = 8000L;                /* ist bei Psion fest */
  492.         new->channels = 1;            /* ist bei Psion fest */
  493.         new->res = 16;                    /* ist bei Psion fest */
  494.  
  495.         /* Dein Einsatz, Thomas */
  496.         convert_alaw_linear(new);
  497.     }
  498.     else if (*fmt_tag == NeXT_HEAD)        /* NeXT-Format ('.snd')*/
  499.     {
  500.         SNDSoundStruct *snd;
  501.  
  502.         snd = (SNDSoundStruct *) adr;
  503.  
  504.         new->len = snd->dataSize;
  505.         new->adr = (WORD *) adr;
  506.         new->end = (WORD *) ((LONG)snd + new->len);
  507.  
  508.         new->frq = snd->samplingRate;
  509.         new->channels = (BYTE) snd->channelCount;
  510.  
  511.         if (snd->dataFormat == SND_FORMAT_UNSPECIFIED)
  512.             ;
  513.         else if (snd->dataFormat == SND_FORMAT_LINEAR_8)
  514.             new->res = 8;
  515.         else if (snd->dataFormat == SND_FORMAT_LINEAR_16)
  516.             new->res = 16;
  517.         else if (snd->dataFormat == SND_FORMAT_MULAW_8)
  518.         {
  519.             return RT_UNSUPPORTED_AU_SND;
  520.     /*        new->res = 16;
  521.     *        ret = convert_mulaw_linear(new);
  522.     *        if (ret != TRUE)
  523.     *        {
  524.     *            if (new->memoryplay == NULL)
  525.     *                OwnMfree(adr);
  526.     *            return ret;
  527.     *        } */
  528.         }
  529.         else
  530.         {
  531.             new->res = 0;
  532.             if (new->memoryplay == NULL)
  533.                 OwnMfree(adr);
  534.             return RT_UNSUPPORTED_AU_SND;
  535.         }
  536.     }
  537.     else
  538.         return RT_WRONG_FILE;
  539.  
  540.     return TRUE;
  541. }
  542.  
  543. /************************************************************************/
  544.  
  545. LOCAL WORD convert_alaw_linear(NEWDEF* new)
  546. {
  547.     WORD *dest;
  548.  
  549.     /* Grö₧e verdoppeln. Es entstehen aus den 8-Bit-Werten zwar nur
  550.         12-Bit-Werte, aber die sind so schlecht zu verwalten. Daher 16-Bit. */
  551.     new->len = new->len << 1;
  552.     dest = OwnMalloc(new->len, MLC_ST_RAM);
  553.     if (dest == NULL)
  554.         return RT_NO_MEM;
  555.     memset(dest, 0, new->len);        /* auf 0 setzen */
  556.  
  557. /*    Hier fehlt der Code, da die mir vorliegenden Tabellen nicht stimmen :-/ */    
  558.  
  559.     return 0;    
  560. }
  561.  
  562. /************************************************************************/
  563.  
  564. LOCAL WORD    play_sample(NEWDEF *new)
  565. {
  566.     WORD ret;
  567.     ULONG frq;
  568.  
  569.     if (new->sample_start == NULL)
  570.         return RT_WRONG_FILE;
  571.  
  572.     if (new->snd_system == HSND_COMP || new->snd_system == MSND_COMP ||
  573.         new->snd_system == F030_COMP || new->snd_system == ST_H_COMP ||
  574.         new->snd_system == ST_W_COMP) 
  575.             ret = flc_play_sam(new);
  576.     else if (new->snd_system == STE_COMP)
  577.     {
  578.         BYTE mode;
  579.  
  580.         if (new->res == 16)
  581.         {
  582.             new->len = (LONG)    to_eight((unsigned char*) new->sample_start,
  583.                                     (unsigned char*)((LONG)new->sample_start + new->len),
  584.                                     TRUE);
  585.             new->len -= (LONG) new->sample_start;
  586.         }
  587.  
  588.         if (new->channels == 2)
  589.             mode = 0;
  590.         else
  591.             mode = 1;
  592.         frq = 1;
  593.  
  594.         if (new->frq > 37549L)
  595.             frq = 3;
  596.         else if (new->frq <= 37549L && new->frq > 18775)
  597.             frq = 2;
  598.         else if (new->frq <= 18775 && new->frq > 9387)
  599.             frq = 1;
  600.         else if (new->frq <= 9387)
  601.             frq = 0;
  602.  
  603.         ste_play_sam((BYTE *)new->sample_start, new->len, (BYTE)frq, mode);
  604.  
  605.         /* warte auf Abbruchbedingung */
  606.         do
  607.         {
  608.             if (sample_interrupt == TRUE)
  609.                 break;
  610.             if (Kbshift(-1) == 4+2)
  611.             {
  612.                 totalbreak = TRUE;
  613.                 break;
  614.             }
  615.  
  616.             /* bis CTRL-SHIFT oder Sample-Ende erreicht */
  617.         } while (ste_ready_sam() == FALSE);
  618.  
  619.         ste_stop_sam();
  620.         ret = TRUE;
  621.     }
  622.     else if (new->snd_system == ST_COMP)
  623.     {
  624.         frq = 614400L / new->frq;
  625.         if (new->res == 16)
  626.         {
  627.             new->len = (LONG)    to_eight((unsigned char*) new->sample_start,
  628.                                     (unsigned char*)((LONG)new->sample_start + new->len),
  629.                                     TRUE);
  630.             new->len -= (LONG) new->sample_start;
  631.         }
  632.         play_init();
  633.  
  634.         play_sam((BYTE*) new->sample_start, new->len, (WORD)frq);
  635.  
  636.         /* warte auf Abbruchbedingung */
  637.         do
  638.         {
  639.             /* bis CTRL-SHIFT oder Sample-Ende erreicht */
  640.             if (sample_interrupt == TRUE)
  641.                 break;
  642.             if (Kbshift(-1) == 4+2)
  643.             {
  644.                 totalbreak = TRUE;
  645.                 break;
  646.             }
  647.         } while (sam_flag & 1);
  648.  
  649.         stop_sam(); play_exit();
  650.         ret = TRUE;
  651.     }
  652.     else
  653.         ret = RT_SND_ERR;
  654.  
  655.     return(ret);
  656. }
  657.  
  658. /************************************************************************/
  659.  
  660. LOCAL WORD flc_play_sam(NEWDEF* new)
  661. {
  662.     LONG        curadder, curadc;
  663.     WORD        prescale;
  664.     DMAPOS    pos;
  665.     BOOLEAN    loop_exit = FALSE, first_flag;
  666.  
  667.     if (locksnd() != 1)            /* sperre Soundsystem */
  668.         return(RT_LOCKED);
  669.  
  670.     if (sndstatus(0))                /* CODEC-Reset, wenn Fehler */
  671.         sndstatus(1);
  672.  
  673.     curadder = soundcmd(ADDERIN, INQUIRE);
  674.     curadc = soundcmd(ADCINPUT, INQUIRE);
  675.     soundcmd(ADCINPUT, 0);
  676.  
  677.     setmontracks(0);    /* Lautsprecher = erste Spur */
  678.  
  679.     if (((soundcmd(7,-1) >= 0) && (new->snd_system == HSND_COMP)) || new->snd_system == ST_W_COMP)    /* wenn WeirdMac oder StarTrack-Karte mit Clockmodul */
  680.     {
  681.         soundcmd(7, (WORD) new->frq); /* ohne feste XBIOS-Frequenzen spielen */
  682.     }
  683.     else
  684.     if (new->snd_system == ST_H_COMP)
  685.     {
  686.         REG LONG f = new->frq;
  687.  
  688.         if (f > 46050L)
  689.             prescale = 3;
  690.         else if (f <= 46050L && f > 38587L)
  691.             prescale = 2;
  692.         else if (f <= 38587L && f > 32537L)
  693.             prescale = 11;
  694.         else if (f <= 32537L && f > 28000)
  695.             prescale = 1;
  696.         else if (f <= 28000 && f > 23025)
  697.             prescale = 10;
  698.         else if (f <= 23025 && f > 19293)
  699.             prescale = 9;
  700.         else if (f <= 19293 && f > 16268)
  701.             prescale = 8;
  702.         else if (f <= 16268 && f > 14000)
  703.             prescale = 7;
  704.         else if (f <= 14000 && f > 11512)
  705.             prescale = 6;
  706.         else if (f <= 11512 && f > 9487)
  707.             prescale = 5;
  708.         else
  709.             prescale = 4;
  710.     }
  711.     else
  712.     {
  713.         if (new->frq > 40975L)
  714.             prescale = 1;
  715.         else if (new->frq < 40975L && new->frq > 28682)
  716.             prescale = 2;
  717.         else if (new->frq <= 28682 && new->frq > 22126)
  718.             prescale = 3;
  719.         else if (new->frq <= 22126 && new->frq > 18029)
  720.             prescale = 4;
  721.         else if (new->frq <= 18029 && new->frq > 14341)
  722.             prescale =  5;
  723.         else if (new->frq <= 14341 && new->frq > 11000)
  724.             prescale = 7;
  725.         else if (new->frq <= 11000 && new->frq > 9014)
  726.             prescale = 9;
  727.         else
  728.             prescale = 11;
  729.     }
  730.  
  731.     if (new->channels == 2)
  732.     {
  733.         if (new->res == 8)
  734.             setmode(STEREO8);
  735.         else if (new->res == 16)
  736.             setmode(STEREO16);
  737.     }
  738.     else if (new->channels == 1)
  739.     {
  740.         if (new->res == 8)
  741.             setmode(MONO8);
  742.     }
  743.  
  744.     setbuffer(0, new->sample_start, new->end);            /* setze DMA Abspielpuffer */
  745.     settracks(0, 0);                        /* eine Wiedergabespur */
  746.  
  747.     devconnect(DMAPLAY, DAC, CLK25M, prescale, NO_SHAKE);
  748.  
  749.     buffoper(PLAY_ENABLE);
  750.     first_flag = TRUE;
  751.  
  752.     /* Zwei Behandlungen, da sich MSND.PRG auf'm Mac anders als der Falcon verhält */
  753.     /* Interrupt-Geschichten führten bei mir auf dem Falcon nur zum Interrupt-Tod,
  754.         kann aber auch an meinem gepatchten TOS gelegen haben. Jetzt ist er platt
  755.         und ich kann es nicht mehr testen. Daher das kranke System des Pointer-
  756.         Abpassens. */
  757.  
  758.     if (new->snd_system == F030_COMP || soundcmd(7,-1)>=0) /* XX */
  759.     {
  760.         do
  761.         {
  762.             buffptr((LONG *) &pos);
  763.             if (first_flag == TRUE)
  764.                 first_flag = FALSE;
  765.             if ((first_flag == FALSE) && (pos.playbufptr == (LONG)new->sample_start))
  766.                 loop_exit = TRUE;
  767.             if (pos.playbufptr >= (LONG)new->end)
  768.                 loop_exit = TRUE;
  769.             if (sample_interrupt == TRUE)
  770.                 break;
  771.             if (Kbshift(-1) == 4+2)
  772.             {
  773.                 totalbreak = TRUE;
  774.                 break;
  775.             }
  776.             Syield();
  777.         }
  778.         while ( loop_exit != TRUE );
  779.     }
  780.     else if (new->snd_system == MSND_COMP)
  781.     {
  782.         do
  783.         {
  784.             buffptr((LONG *) &pos);
  785.             if (sample_interrupt == TRUE)
  786.                 break;
  787.             if (Kbshift(-1) == 4+2)
  788.             {
  789.                 totalbreak = TRUE;
  790.                 break;
  791.             }
  792.             Syield();
  793.         } while (pos.playbufptr != (LONG) new->end);
  794.     }
  795.  
  796.     buffoper(0);    /* setze die Ursprungsdaten ... */
  797.  
  798.     soundcmd(ADDERIN, (WORD) curadder);
  799.     soundcmd(ADCINPUT, (WORD) curadc);
  800.  
  801.     unlocksnd();
  802.     return (TRUE);
  803. }
  804.  
  805. /************************************************************************/
  806.  
  807. LONG FileLen(CONST BYTE *fname)
  808. {
  809.     LONG back;
  810.     WORD handle;
  811.     LONG flen = 0;
  812.     XATTR xattr;
  813.  
  814.     xattr.size = 0;
  815.  
  816.     back = Fxattr(0, (BYTE *)fname, (XATTR*) &xattr);
  817.     if (back == -32L)        /* wenn es Fxattr nicht gibt */
  818.     {
  819.         back = Fopen(fname, FO_READ);
  820.         if (back < 0) return(FALSE);
  821.     
  822.         handle = (WORD) back;
  823.     
  824.         flen = Fseek(0, handle, 2);        /* ans Dateiende springen */
  825.     
  826.         if (Fclose(handle) != 0) return(FALSE);
  827.     
  828.         return flen;
  829.     }
  830.     else
  831.         return xattr.size;
  832. }
  833.  
  834. /************************************************************************/
  835.  
  836. LOCAL BOOLEAN IsThereMxalloc(VOID)
  837. {
  838.     LONG dum = (LONG)Mxalloc(-1,0);
  839.     if (dum == -32L)
  840.         return(FALSE);
  841.     else
  842.         return(TRUE);
  843. }
  844.  
  845. /************************************************************************/
  846.  
  847. LOCAL BOOLEAN IsThereFastRAM(VOID)
  848. {
  849.     VOID *dum;
  850.     if (IsThereMxalloc() == TRUE)
  851.     {
  852.         dum = Mxalloc(64, 1);    /* 64 Bytes alt. RAM holen */
  853.         if (dum != NULL)            /* da? */
  854.         {
  855.             Mfree(dum);
  856.             return(TRUE);
  857.         } else
  858.             return(FALSE);
  859.     } else
  860.         return(FALSE);    /* FAST-RAM ist vielleicht da, aber kein Mxalloc */
  861. }
  862.  
  863. /************************************************************************/
  864.  
  865. VOID *OwnMalloc(CONST LONG amount, CONST WORD typ)
  866. {
  867.     if (IsThereMxalloc() == TRUE)
  868.     {
  869.         /* unter MagiCMac ist es egal, ob ST- oder TT-RAM angefordert wird */
  870.         if (MagiCMac == TRUE)
  871.             return(Mxalloc(amount, MLC_TTST_RAM));
  872.         return(Mxalloc(amount, typ));
  873.     }
  874.     else 
  875.         return(Malloc(amount));
  876. }
  877.  
  878. /************************************************************************/
  879.  
  880. VOID OwnMfree(CONST VOID *adr)
  881. {
  882.     Mfree(adr);
  883. }
  884.  
  885. /************************************************************************/
  886.  
  887. LOCAL BOOLEAN Laden(CONST BYTE *fname, BYTE *addr, CONST LONG len)
  888. {
  889.     LONG        handle;
  890.     BOOLEAN    back;
  891.     WORD        h;
  892.     
  893.     handle = Fopen(fname, FO_READ);
  894.     if (handle < 0)
  895.         return(FALSE);
  896.     h = (WORD)handle;
  897.     if (Fread(h, len, addr) != len)
  898.         back = FALSE;
  899.     else
  900.         back = TRUE;
  901.     Fclose(h);
  902.     return(back);
  903. } /* laden */
  904.  
  905. /************************************************************************/
  906.  
  907. LOCAL VOID flip_word (REG BYTE *adr)
  908. {
  909.   REG BYTE c;
  910.  
  911.   c       = adr [0];
  912.   adr [0] = adr [1];
  913.   adr [1] = c;
  914. } /* flip_word */
  915.  
  916. /************************************************************************/
  917.  
  918. LOCAL VOID flip_long (REG WORD *adr)
  919. {
  920.   REG WORD i;
  921.  
  922.   i       = adr [0];
  923.   adr [0] = adr [1];
  924.   adr [1] = i;
  925.  
  926.   flip_word ((BYTE *)&adr [0]);
  927.   flip_word ((BYTE *)&adr [1]);
  928. } /* flip_long */
  929.  
  930. /************************************************************************/
  931.  
  932. /** Profibuch v. Jankowski/Rabich/Reschke    **/
  933. /** 10. Auflage, S. 74                             **/
  934. /** verändert: Supexec(), 1999-02-14        **/
  935. /** verändert: Setexc(), 1999-04-06            **/
  936. WORD get_cookie(CONST LONG cookie, LONG *value)
  937. {
  938.     /* Zeiger auf Cookie Jar holen */
  939.     LONG *cookiejar = (LONG *) Setexc(0x5A0/4, (void (*)())-1);
  940.  
  941.     /* Cookiejar überhaupt vorhanden ? */
  942.     if (cookiejar == NULL)
  943.         return(FALSE);
  944.  
  945.     do
  946.     {
  947.         /* Cookie gefunden ? */
  948.         if (cookiejar[0] == cookie)
  949.         {
  950.             /* nur eintragen, wenn "value" kein Nullpointer */
  951.             if (value)
  952.                 *value = cookiejar[1];
  953.             return(TRUE);
  954.         }
  955.         else
  956.         {
  957.             /* nächsten Cookie nehmen */
  958.             cookiejar = &(cookiejar[2]);
  959.         }
  960.     } while (cookiejar[-2]); /* Nullcookie? */
  961.     return (FALSE);
  962. }
  963.  
  964. /************************************************************************/
  965. VOID    handle_SIGUSR1(VOID)
  966. {
  967.     sample_interrupt = TRUE;
  968.     totalbreak = TRUE;
  969. }
  970.  
  971. /************************************************************************/
  972. VOID    handle_SIGTERM(VOID)
  973. {
  974.     sample_interrupt = TRUE;
  975.     totalbreak = TRUE;
  976.     quit = TRUE;
  977. }
  978.  
  979. /************************************************************************/
  980. WORD convert_mulaw_linear(NEWDEF *new)
  981. {
  982.     /* 8 Bit u-law nach 16 Bit linear Wandlung */
  983.     /* XXX: funktioniert leider nicht, nochmal angucken */
  984.  
  985.     REG BYTE *look_index;
  986.     WORD *expanded;
  987.  
  988.     expanded = OwnMalloc(new->len * 2, MLC_ST_RAM);    /* neuen Speicherblock holen */
  989.  
  990.     if (expanded == NULL)
  991.         return RT_NO_MEM;
  992.  
  993.     look_index = (BYTE *) new->adr;                    /* XXX */
  994.     while ((LONG)look_index < (LONG) new->end)
  995.     {
  996.         *expanded = lookup[*look_index];
  997.         expanded++;
  998.         look_index++;
  999.     }
  1000.  
  1001.     OwnMfree(new->adr);    /* alten Speicherblock freigeben, führt leider zur Zersplitterung */
  1002.  
  1003.     new->sample_start = new->adr = expanded;
  1004.     new->end = (WORD *)((LONG) expanded + new->len *2);
  1005.     new->len = new->len * 2;
  1006.  
  1007.     return TRUE;
  1008. }
  1009.