home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / programs / programming / stuff / BBCtape / c / asave
Encoding:
Text File  |  1998-02-07  |  21.1 KB  |  773 lines

  1. /* >>>>>>>>>>>>>>>>>>> The BBC Tape Utility <<<<<<<<<<<<<<<<<<<<<<<<<
  2.  *
  3.  * Copyright (c) Ole Stauning 1996.
  4.  *
  5.  * Permission to use, copy, modify, distribute, and sell this software
  6.  * and its documentation for any purpose is hereby granted without fee,
  7.  * provided that the above copyright notice appear in all copies and
  8.  * that both that copyright notice and this permission notice appear in
  9.  * supporting documentation, and that the name of the copyright holder
  10.  * not be used in advertising or publicity pertaining to distribution
  11.  * of the software without specific, written prior permission. The
  12.  * copyright holder makes no representations about the suitability of
  13.  * this software for any purpose. It is provided "as is" without express
  14.  * or implied warranty.
  15.  *
  16.  * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  17.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  18.  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
  19.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  20.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  21.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  22.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23.  *
  24.  *  So if you fry your soundcard, do not blame it on me :-)
  25.  *
  26.  *  Please send comments, questions, bug-reports and flames to 
  27.  *
  28.  *                        os@imm.dtu.dk
  29.  */
  30.  
  31. #include "patch.h"  /* try to get it going */
  32.  
  33. #include <math.h>
  34. #include <stdio.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <signal.h>
  39.  
  40. /* >>>>> SPECIFIC BBC FILE FORMAT STUFF <<<<<< */
  41.  
  42. #define DEFAULT_AUDIO_DEV "/dev/dsp"
  43. #define DEFAULT_SAMPLE_FREQ 44100
  44. #define DEFAULT_BAUD_RATE 1200
  45. #define DEFAULT_BLOCK_SIZE 256
  46. #define DEFAULT_START_BITS 0
  47. #define DEFAULT_NUMBER_OF_START_BITS 1
  48. #define DEFAULT_STOP_BITS 1
  49. #define DEFAULT_NUMBER_OF_STOP_BITS 1
  50. #define DEFAULT_START_STOP_BITS "0/1"
  51.  
  52. #define SIGNAL_AMP 100
  53. #define SIGNAL_ZERO 128
  54. #define SIGNAL_PHASE -1
  55. #define SYNC_BYTE 0x2a
  56. #define SYNC_BUGF 0xaa
  57. #define DATA_BITS 8
  58. #define HEADER_SPACE 6000
  59. #define BLOCK_SPACE 1200
  60. #define SYNC_LENGTH 500
  61.  
  62. #define NO_ERROR 0
  63. #define BAD_AUDIO 1
  64. #define WRONG_BLOCK 2
  65. #define END_OF_AUDIO 3 
  66.  
  67. int BAUD_RATE=DEFAULT_BAUD_RATE,
  68.     SAMPLE_FREQ=DEFAULT_SAMPLE_FREQ,
  69.     BLOCK_SIZE=DEFAULT_BLOCK_SIZE,
  70.     START_BITS=DEFAULT_START_BITS,
  71.     NUMBER_OF_START_BITS=DEFAULT_NUMBER_OF_START_BITS,
  72.     STOP_BITS=DEFAULT_STOP_BITS,
  73.     NUMBER_OF_STOP_BITS=DEFAULT_NUMBER_OF_STOP_BITS;
  74.     
  75. u_char TAPE_FILENAME[255]; /* length should be <= 10, but anyway, it might be usefull??*/
  76. u_long LOAD_ADDRESS,EXEC_ADDRESS;
  77.  
  78. /* >>>>> END OF SPECIFIC BBC FILE FORMAT STUFF <<<<<< */
  79.  
  80. u_char AUDIO_DEV[30]=DEFAULT_AUDIO_DEV;
  81. u_char WAV_FILE[255];
  82.  
  83. int audio, stopflag = 0;
  84.     
  85. int USE_WAV_FILE=0;
  86. u_char *command;
  87.  
  88. /* the save wave table */
  89. u_char *one,*zero;
  90. int length;
  91.  
  92. /* some signal specific variables. Used in loading */
  93. int dsp_int=0,load_int=0; 
  94.  
  95. int synccount=0,i=0;
  96.  
  97. /* input audio buffers */
  98. #define AUDIO_BUFFERS 2
  99. u_char *audiobufs[AUDIO_BUFFERS],*audiobuf;
  100. int *audiobufs_length;
  101. int abuf_size,abuf_index,abuf_number;
  102.  
  103. /* The crc variable */
  104.  
  105. u_short crc;
  106.  
  107. /* Definitions for Micro$oft WAVE format */
  108.  
  109. #define RIFF        0x46464952    
  110. #define WAVE        0x45564157
  111. #define FMT        0x20746D66
  112. #define DATA        0x61746164
  113. #define PCM_CODE    1
  114. #define WAVE_MONO    1
  115. #define WAVE_STEREO    2
  116.      
  117. typedef struct _waveheader {
  118.   u_long    main_chunk;    /* 'RIFF' */
  119.   u_long    length;        /* filelen */
  120.   u_long    chunk_type;    /* 'WAVE' */
  121.  
  122.   u_long    sub_chunk;    /* 'fmt ' */
  123.   u_long    sc_len;        /* length of sub_chunk, =16 */
  124.   u_short    format;        /* should be 1 for PCM-code */
  125.   u_short    modus;        /* 1 Mono, 2 Stereo */
  126.   u_long    sample_fq;    /* frequence of sample */
  127.   u_long    byte_p_sec;
  128.   u_short    byte_p_spl;    /* samplesize; 1 or 2 bytes */
  129.   u_short    bit_p_spl;    /* 8, 12 or 16 bit */ 
  130.  
  131.   u_long    data_chunk;    /* 'data' */
  132.   u_long    data_length;    /* samplecount */
  133. } WaveHeader;  
  134.  
  135. void write_wav_header(int fd){ /* write a WAVE-header */
  136.   WaveHeader wh;
  137.  
  138.   wh.main_chunk = RIFF;
  139.   wh.length     = 0 + sizeof(WaveHeader) - 8; 
  140.   wh.chunk_type = WAVE;
  141.   wh.sub_chunk  = FMT;
  142.   wh.sc_len     = 16;
  143.   wh.format     = PCM_CODE;
  144.   wh.modus      = 1; /* mono */
  145.   wh.sample_fq  = SAMPLE_FREQ ;
  146.   wh.byte_p_spl = 1; /* 1 byte sample size */
  147.   wh.byte_p_sec = wh.sample_fq * wh.modus * wh.byte_p_spl;
  148.   wh.bit_p_spl  = 8; /* 8 byte sample size */
  149.   wh.data_chunk = DATA;
  150.   wh.data_length= 0x7fffffff; /* Only stupid WINDOZE programs use this */
  151.   write (fd, &wh, sizeof(WaveHeader));
  152. }
  153.  
  154. void test_wavefile(int audio)
  155.      { /* test a WAVE-header */
  156.       WaveHeader *wp;
  157.      
  158.       if ((wp=malloc(sizeof(WaveHeader)))==NULL)
  159.          {
  160.           fprintf(stderr,"%s: Unable to allocate wave header buffer for input\n",command);
  161.           exit(-1);
  162.          }
  163.       read(audio,(u_char *)wp, sizeof(WaveHeader));
  164.   
  165.       if (wp->main_chunk != RIFF || wp->chunk_type != WAVE ||
  166.           wp->sub_chunk != FMT || wp->data_chunk != DATA) 
  167.          {
  168.           fprintf (stderr, "%s: This is not a WAV format file, trying raw.\n", command);
  169.          } 
  170.       else 
  171.          {
  172.           if (wp->format != PCM_CODE)
  173.              {
  174.               fprintf (stderr, "%s: can't decode not PCM-coded WAVE-files\n", command);
  175.               exit (-1);
  176.              }
  177.           if (wp->modus > 1) 
  178.              {
  179.               fprintf (stderr, "%s: can only decode mono WAVE-files\n", command);
  180.               exit (-1);
  181.              }
  182.           if (wp->bit_p_spl!=8)
  183.              {
  184.               fprintf (stderr, "%s: can only decode 8 bit WAVE-files\n", command);
  185.               exit (-1);
  186.              }
  187.           SAMPLE_FREQ = wp->sample_fq;   
  188.          }
  189.   free(wp);
  190. }
  191.  
  192. /* end of definitions for Micro$oft WAVE format */
  193.  
  194. /* Removed in a fit of patching */
  195.  
  196.  
  197. void clear_crc(){
  198.   crc=0;
  199. }
  200.  
  201. u_short read_crc(){
  202.   return crc;
  203. }
  204.  
  205. void byte2crc(u_char b){
  206. int i;
  207.  
  208.   crc^=b<<8;
  209.   for(i=0;i<8;i++) 
  210.     crc = (crc&0x8000) ? ( (crc ^ 0x810) << 1 ) | 1 : crc << 1;   
  211. }
  212.  
  213. void make_wave_table(){
  214.  int i;
  215.   length=SAMPLE_FREQ/BAUD_RATE;
  216.   if ((zero=malloc(length))==NULL || (one=malloc(length))==NULL){
  217.     fprintf(stderr,"%s: Unable to allocate audio buffer for output\n",command);
  218.     exit(-1);
  219.   }
  220.   for(i=0;i<length;i++) /* zero wave table */
  221.     zero[i]=SIGNAL_ZERO+SIGNAL_AMP*SIGNAL_PHASE*sin((2.0*M_PI*i)/length);
  222.   for(i=0;i<length;i++) /* one wave table  */
  223.     one[i]=zero[(2*i)%length];                                          
  224. }
  225.  
  226. void delete_wave_table(){
  227.   free(zero);free(one);
  228. }
  229.  
  230. void save_byte(int audio, u_char b){
  231. int i;
  232. u_char *onezero;
  233.  
  234.   byte2crc(b); /* update the crc value */
  235.  
  236.   for(i=0;i<NUMBER_OF_START_BITS;i++){ /* first write the start bits */
  237.     onezero=(START_BITS&(1<<i)) ? one : zero;
  238.     if (write(audio,onezero,length)!=length){
  239.       exit(-1);
  240.     }
  241.   }
  242.   for(i=0;i<DATA_BITS;i++){ /* then write the data */
  243.     onezero=(b&(1<<i)) ? one : zero;
  244.     if (write(audio,onezero,length)!=length){
  245.       exit(-1);
  246.     }
  247.   }
  248.   for(i=0;i<NUMBER_OF_STOP_BITS;i++){ /* finally write the stop bits */
  249.     onezero=(STOP_BITS&(1<<i)) ? one : zero;
  250.     if (write(audio,onezero,length)!=length){
  251.       exit(-1);
  252.     }
  253.   }
  254. }
  255.  
  256. void save_long(int audio,u_long ul){
  257. int i;
  258.   for(i=0;i<4;i++){
  259.     save_byte(audio,ul&0xff);
  260.     ul>>=8;
  261.   }
  262. }    
  263.  
  264. void save_short(int audio,u_short us){
  265. int i;
  266.   for(i=0;i<2;i++){
  267.     save_byte(audio,us&0xff);
  268.     us>>=8;
  269.   }
  270. }    
  271.  
  272. void make_sync(int audio,int sync_length){ /* create the tone */ 
  273. int i; 
  274.   
  275.   for(i=0;i<sync_length;i++) 
  276.     if (write(audio,one,length)!=length){
  277.       exit(-1);
  278.     }
  279. }
  280.           
  281. void save(int source, int audio){
  282. int i;
  283. u_char *data,flags;
  284. u_short block=0,block_length,CRC;
  285.  
  286.   if ((data=malloc(BLOCK_SIZE))==NULL){
  287.     fprintf(stderr,"%s: Unable to allocate data buffer\n",command);
  288.     exit(-1);
  289.   }
  290.   
  291.   make_wave_table(); /* initialize the sound tables */
  292.     
  293.   make_sync(audio,HEADER_SPACE); /* create the file header tone */ 
  294.      
  295.   while((block_length=read(source,data,BLOCK_SIZE))>0){
  296.  
  297.     /* write the header first: */ 
  298.   
  299.     save_byte(audio,(u_char)0x2a); /* sync byte */
  300.     
  301.     clear_crc(); /* refresh the crc */
  302.     
  303.     for(i=0;TAPE_FILENAME[i]!='\0';i++)
  304.       save_byte(audio,TAPE_FILENAME[i]);    
  305.     save_byte(audio,(u_char)0x00);
  306.     fprintf(stderr,"%s ",TAPE_FILENAME);
  307.     save_long(audio,LOAD_ADDRESS);
  308.     fprintf(stderr,"%8.8x ",LOAD_ADDRESS);
  309.     save_long(audio,EXEC_ADDRESS);
  310.     fprintf(stderr,"%8.8x ",EXEC_ADDRESS);
  311.     save_short(audio,block);
  312.     fprintf(stderr,"%2.2x ",block++);
  313.     save_short(audio,block_length);
  314.     fprintf(stderr,"%4.4x ",block_length);
  315.     flags=(block_length!=BLOCK_SIZE)<<7;
  316.     save_byte(audio,flags);
  317.     fprintf(stderr,"%2.2x \n",flags);
  318.     save_long(audio,0);
  319.     
  320.     CRC=read_crc();
  321.     CRC=((CRC&0xff00)>>8)|((CRC&0x00ff)<<8); /* Why this? is it more safe */
  322.     save_short(audio,CRC);
  323.     
  324.     clear_crc(); /* refresh the crc */
  325.     
  326.     /* now flush the data */
  327.     
  328.     for(i=0;i<block_length;i++)
  329.       save_byte(audio,data[i]);
  330.      
  331.     /* and write data CRC */
  332.     
  333.     CRC=read_crc();
  334.     CRC=((CRC&0xff00)>>8)|((CRC&0x00ff)<<8); /* Why this? is it more safe */
  335.     save_short(audio,CRC);
  336.      
  337.     make_sync(audio,BLOCK_SPACE); /* block sync tone */
  338.     
  339.   }  
  340.   delete_wave_table(); /* clean up before we leave */ 
  341. }     
  342.  
  343. void dsp_handler(int dummy){ /* hey, someone is calling dsp child */
  344.   dsp_int=1;
  345.  
  346. void dsp_pause(){
  347.      /* Here we must get new data into 'shared' buffer
  348.           (or so it seems) */
  349.           
  350.           if ((audiobufs_length[i]=read(audio,audiobufs[i],abuf_size))==0)
  351.              stopflag = 1;
  352.           
  353.           i=(i+1)%AUDIO_BUFFERS;
  354. }
  355.  
  356. void load_pause(){
  357.   load_int=0;
  358. }
  359.  
  360. int re_sample(int* s, double interval, int n){
  361. int old_abuf_index=abuf_index;
  362. register int i;
  363.  
  364.   for(i=0;i<=n;i++){
  365.     abuf_index=old_abuf_index+rint((interval*i)/n);
  366.     
  367.     if (abuf_index>=audiobufs_length[abuf_number]) {  /* Buffer shift */    
  368.  
  369.       dsp_pause(); /* await a new workload from parent */
  370.                    /* Should be ok */
  371.     
  372.       old_abuf_index-=audiobufs_length[abuf_number];
  373.       abuf_index%=audiobufs_length[abuf_number];
  374.       abuf_number=(abuf_number+1)%AUDIO_BUFFERS;
  375.       if (audiobufs_length[abuf_number]<=0) { 
  376.         fprintf(stderr," end of audio reached! \n");
  377.         return END_OF_AUDIO; /* end of audio */
  378.       }
  379.     }
  380.     s[i]=(int)audiobufs[abuf_number][abuf_index];
  381.   }
  382.   return NO_ERROR;
  383. }
  384.  
  385. int load_byte(u_char *b){
  386. static int mask[2],i,bit,idx,status;
  387. double track=0;
  388. int error=0,s[5],d;
  389.  
  390.   status=idx=0;
  391.   (*b)=0;
  392.        
  393.   while(status<3 && !error){
  394.    
  395.     for(i=0;i<2;i++) { /* sample the next two half bauds */
  396.  
  397.       error=re_sample(s,((double)SAMPLE_FREQ)/(2*BAUD_RATE)+track,4); 
  398.        
  399.       mask[i]= ((3*s[1]>s[0]+s[2]+s[4])<<1 | (3*s[3]>s[0]+s[2]+s[4])) ^ ((SIGNAL_PHASE==-1)?0x3:0x0);
  400.    
  401.       switch (mask[i]) { /* the calculation of track is done in doubles to get nice rounding. */
  402.                          /* the value of track has actually a physical meaning. If you really */
  403.                          /* want to know then email me.                                       */
  404.  
  405.         case 0x03:/* 11 -> bit=0 */
  406.           if ((d=s[4]+s[0])>0)
  407.             track=((double)s[4]-s[0])*SIGNAL_PHASE*SAMPLE_FREQ/(d*8.*BAUD_RATE);  
  408.           break;
  409.               
  410.         case 0x02:/* 10 -> bit=1 */
  411.           if ((d=s[2]+s[4])>0)
  412.             track=((double)s[2]-s[4])*SIGNAL_PHASE*SAMPLE_FREQ/(d*8.*BAUD_RATE);  
  413.           break;
  414.             
  415.         case 0x01:/* 01 -> bit=1 */
  416.           if ((d=s[4]+s[2])>0)
  417.             track=((double)s[4]-s[2])*SIGNAL_PHASE*SAMPLE_FREQ/(d*8.*BAUD_RATE);  
  418.       break;
  419.     
  420.         case 0x00:/* 00 -> bit=0 */
  421.           if ((d=s[0]+s[4])>0)
  422.             track=((double)s[0]-s[4])*SIGNAL_PHASE*SAMPLE_FREQ/(d*8.*BAUD_RATE);  
  423.           break;
  424.     
  425.         default:
  426.           track=1; /* Just to avoid getting stuck in a perfect reverse phase */
  427.       }         
  428.     }
  429.  
  430.     switch (mask[0]<<2 | mask[1]) { 
  431.       case 0x0c:/* 1100 -> bit=0 */
  432.       case 0x03:
  433.         bit=0;
  434.         if (synccount<SYNC_LENGTH) synccount=0; 
  435.         break;
  436.               
  437.       case 0x0a:/* 1010 -> bit=1 */
  438.       case 0x05:
  439.         bit=1;
  440.     if (synccount<SYNC_LENGTH && ++synccount+1==SYNC_LENGTH) { /* This is also the sync tone */
  441.           fprintf(stderr,"Sync tone detected\n");
  442.           synccount=SYNC_LENGTH;
  443.         }
  444.         break;
  445.         
  446.       case 0x02:/* 0010 -> bit=0 */
  447.       case 0x0d:
  448.         bit=0;
  449.     if (synccount<SYNC_LENGTH) synccount=0;
  450.         break;
  451.         
  452.       case 0x0b:/* 1011 -> bit=1 */
  453.       case 0x04:
  454.         bit=1;
  455.     if (synccount<SYNC_LENGTH) synccount=0;
  456.     break;
  457.     
  458.       default:
  459.         if (synccount==SYNC_LENGTH) { /* Arghh! all is lost */
  460.           fprintf(stderr,"%s: unknown signal\n",command); 
  461.         }
  462.         synccount=0;  /* no sync */
  463.         bit=2;   /* Its an X-bit, uhhh */
  464.     }
  465.  
  466.     if (synccount==SYNC_LENGTH) { /* we are on the right track */
  467.       switch (status) {
  468.         case 0 : /* waiting for startbits */
  469.           if ((bit<<idx)==(START_BITS&(1<<idx))) {
  470.             idx++;
  471.             if (idx==NUMBER_OF_START_BITS) {
  472.               status=1;idx=0; /* now read the byte */
  473.             }
  474.           } else 
  475.               if (idx>0) { 
  476.                 fprintf(stderr,"%s: startbit not correct\n",command);
  477.                 error=BAD_AUDIO;
  478.               }
  479.           break;
  480.           
  481.         case 1 : /* loading data bits     */
  482.           (*b)|=(bit<<idx++);
  483.           if (idx==DATA_BITS) {
  484.             byte2crc(*b); /* include the new byte in the crc value */
  485.             status=2;idx=0; /* now expect some stopbits */
  486.           }
  487.           break;
  488.           
  489.         case 2 : /* loading stopbits     */
  490.           if ((bit<<idx)==(STOP_BITS&(1<<idx))) {
  491.             idx++;
  492.             if (idx==NUMBER_OF_STOP_BITS) status=3; /* The byte is ready for delivery */
  493.           } else { 
  494.               fprintf(stderr,"%s: stopbit not correct\n",command);
  495.               error=BAD_AUDIO;
  496.             }
  497.       }
  498.     } 
  499.   }             
  500.   return error;       
  501. }
  502.   
  503. int load_long(u_long* ul){
  504. int i,error=0;
  505. u_char b;
  506.   (*ul)=0;
  507.   for(i=0;i<4 && !error;i++){
  508.     error=load_byte(&b);
  509.     (*ul)|=b<<(i*8);
  510.   }
  511.   return error;
  512. }   
  513.  
  514. int load_short(u_short* us){
  515. int i,error=0;
  516. u_char b;
  517.   (*us)=0;
  518.   for(i=0;i<2 && !error;i++){
  519.     error=load_byte(&b);
  520.     (*us)|=b<<(i*8);
  521.   }
  522.   return error;
  523. }   
  524.  
  525. void load(int data,int audio){
  526. int i;
  527. u_char *incoming,byte,flags;
  528. int error;
  529. u_long extra;
  530. u_short block_length,block,expected_block,CCRC,CRC;
  531.  
  532.   /* First allocate some 'shared' memory */
  533.  
  534.   if (abuf_size==0) abuf_size=65536;  /* we are reading from file (i hope) */ 
  535.  
  536.   /* audiobuf = 'shared' memory area
  537.   
  538.      size abuf_size*AUDIO_BUFFERS */
  539.  
  540.   audiobuf = malloc(abuf_size*AUDIO_BUFFERS);   /* Am I right in this assumption?*/
  541.   audiobufs_length = (int*)malloc(sizeof(int)*AUDIO_BUFFERS);
  542.  
  543.   
  544.   for(i=0;i<AUDIO_BUFFERS;i++) /* audio buffer array */
  545.     audiobufs[i]=audiobuf+i*abuf_size; 
  546.  
  547.     {
  548.     *audiobuf=1; /* ok! ready, signalling set up. */
  549.      
  550.     dsp_pause(); /* get the first workload */
  551.        
  552.     abuf_index=abuf_number=0;   
  553.        
  554.     flags=0;error=0;expected_block=0;
  555.     
  556.     while(!(flags&0x80)&& !error){   
  557.     
  558.       error=load_byte(&byte); /* sync byte */
  559.       
  560.       if (!error && block==0 && byte==SYNC_BUGF) {
  561.         fprintf(stderr,"%s: sync bug fix byte %2x received\n",command,byte);
  562.         error=load_byte(&byte); /* sync byte */
  563.       }
  564.       
  565.       if (!error && byte!=SYNC_BYTE) {
  566.         fprintf(stderr,"%s: unknown magic number %2x\n",command,byte);
  567.         error=1;        
  568.       }
  569.       
  570.       clear_crc(); /* start from a fresh crc value */
  571.             
  572.       i=0;byte=1;
  573.       while(!error && byte>0) {
  574.         error=load_byte(&byte); 
  575.         TAPE_FILENAME[i++]=byte;
  576.       }
  577.       if (!error) fprintf(stderr,"%s ",TAPE_FILENAME);
  578.       if (!error) error=load_long(&LOAD_ADDRESS);
  579.       if (!error) fprintf(stderr,"%8.8x ",LOAD_ADDRESS);
  580.       if (!error) error=load_long(&EXEC_ADDRESS);
  581.       if (!error) fprintf(stderr,"%8.8x ",EXEC_ADDRESS);
  582.       if (!error) error=load_short(&block);
  583.       if (!error) fprintf(stderr,"%2.2x ",block);
  584.       if (!error) error=load_short(&block_length);
  585.       if (!error) fprintf(stderr,"%4.4x ",block_length);
  586.       if (!error) error=load_byte(&flags);
  587.       if (!error) fprintf(stderr,"%2.2x \n",flags);
  588.       if (!error) error=load_long(&extra);  
  589.      
  590.       CCRC=read_crc();
  591.       if (!error) error=load_short(&CRC); 
  592.       CRC=((CRC&0xff00)>>8)|((CRC&0x00ff)<<8);/*  Why this? is it more safe */
  593.       if (!error && CRC!=CCRC) {
  594.         fprintf(stderr,"%s: CRC check failed for header\n",command);
  595.         error=BAD_AUDIO;         
  596.       }
  597.       
  598.       if (!error && expected_block!=block)
  599.         fprintf(stderr,"%s: WARNING expecting block %2.2x.\n",command,expected_block);
  600.                 
  601.       if (!error) {
  602.         if ((incoming=malloc(block_length))==NULL){
  603.           fprintf(stderr,"%s: Unable to allocate data buffer for input\n",command);
  604.           exit(-1);
  605.         }
  606.   
  607.         clear_crc(); /* start from a fresh crc value */
  608.      
  609.         /* now load the data */
  610.     
  611.         for(i=0;i<block_length && !error | stopflag;i++) {
  612.           error=load_byte(&byte);
  613.           incoming[i]=byte;
  614.         }
  615.      
  616.         /* and now the CRC stuff */
  617.     
  618.         CCRC=read_crc();
  619.         if (!error) error=load_short(&CRC);
  620.         CRC=((CRC&0xff00)>>8)|((CRC&0x00ff)<<8);/*  Why this? is it more safe */
  621.         if (!error && CRC!=CCRC) {
  622.           fprintf(stderr,"%s: CRC check failed for data block\n",command);
  623.           error=BAD_AUDIO;        
  624.         }
  625.         
  626.         if (!error && expected_block==block) 
  627.           if (write(data,incoming,block_length)!=block_length){
  628.             fprintf(stderr,"%s: error writing data\n",command);
  629.             exit(-1);
  630.           }
  631.   
  632.         free(incoming); 
  633.       }
  634.       if (!error && expected_block==block) expected_block++; /* just perfect */
  635.       else if (error!=END_OF_AUDIO) { /* we just try again */
  636.         error=NO_ERROR;
  637.         synccount=0;
  638.       }
  639.     }
  640.   } 
  641. }
  642.  
  643. void usage(){
  644.  fprintf(stderr,"Usage:\n");
  645.  fprintf(stderr,"aload wav-filename data-filename sample-freq baud 0/1\n", command);
  646.  fprintf(stderr,"asave wav-filename data-filename sample-freq baud 0/1 header load exec\n", command);
  647.  exit (-1);
  648. }
  649.  
  650. int getoptions(int argc, char *argv[]){
  651. char c;
  652. char optarg[256]="";
  653. int i;
  654.  
  655.   USE_WAV_FILE=1;
  656.  
  657.   strcpy((char *)WAV_FILE, argv[2]);
  658.   
  659.   fprintf(stderr, "bbctape: wavfile == %s\n", WAV_FILE);
  660.   
  661.   strcpy((char *)AUDIO_DEV,argv[1]); 
  662.   fprintf(stderr, "bbctape: datafile == %s\n", AUDIO_DEV);
  663.  
  664.   strcpy(optarg,argv[3]); 
  665.   SAMPLE_FREQ=atoi(optarg);
  666.   fprintf(stderr, "bbctape: SAMPLE_FREQ == %d\n", SAMPLE_FREQ);
  667.   
  668.   
  669.  
  670.   strcpy(optarg,argv[4]); 
  671.   BAUD_RATE=atoi(optarg);
  672.   fprintf(stderr, "bbctape: BAUD_RATE == %d\n", BAUD_RATE);
  673.  
  674.   /* Fix this */
  675.   BLOCK_SIZE=256;
  676.  
  677.   NUMBER_OF_STOP_BITS=0;
  678.   NUMBER_OF_START_BITS=0;
  679.   STOP_BITS=START_BITS=0;
  680.  
  681.   strcpy(optarg,argv[5]); 
  682.  
  683.   for(i=0;optarg[i]!='/';i++) 
  684.      if (optarg[i]=='1') 
  685.         START_BITS |= 1<<i;
  686.      else 
  687.         if (optarg[i]!='0') usage();
  688.           
  689.      if ((NUMBER_OF_START_BITS=i)==0){
  690.         fprintf(stderr,"%s: you must have startbits\n",command);
  691.         exit(-1);
  692.         }        
  693.      for(i++;optarg[i]!='\0';i++) 
  694.         if (optarg[i]=='1') 
  695.             STOP_BITS |= 1<<(i-NUMBER_OF_START_BITS-1);
  696.         else 
  697.             if (optarg[i]!='0') usage();
  698.             
  699.         if ((NUMBER_OF_STOP_BITS=i-NUMBER_OF_START_BITS-1)==0){
  700.            fprintf(stderr,"%s: you must have stopbits\n",command);
  701.           exit(-1);
  702.         }        
  703.         
  704.         if (START_BITS&1){
  705.           fprintf(stderr,"%s: first startbit has to be 0\n",command);
  706.           exit(-1);
  707.         }
  708.   return 0;
  709. }
  710.  
  711. void bbc_load(int argc, char *argv[]){
  712. int optind,data;
  713.  
  714.   optind=getoptions(argc,argv);
  715.  
  716.   audio = open((char *)WAV_FILE, O_RDONLY, 0);  /* the wav file is coming from disk */
  717.   test_wavefile(audio);
  718.  
  719.   data = open( (char *)AUDIO_DEV, O_WRONLY | O_CREAT, 0666); /* write data to file */
  720.  
  721.   load(data,audio);             /* Call fn to do the work */
  722.   close(data);                  /* Close files */
  723.   close(audio);
  724. }
  725.  
  726. void bbc_save(int argc, char *argv[]){
  727. int idx,data;
  728.  
  729.   idx=getoptions(argc,argv);
  730.  
  731.   strcpy((char *)TAPE_FILENAME,argv[6]); 
  732.   
  733.   fprintf(stderr, "bbctape: tape filename == %s\n", TAPE_FILENAME);
  734.  
  735.   LOAD_ADDRESS=strtol(argv[7],NULL,0);
  736.   
  737.   fprintf(stderr, "bbctape: load address == %d\n", LOAD_ADDRESS);
  738.   
  739.   
  740.   EXEC_ADDRESS=strtol(argv[8],NULL,0);
  741.   fprintf(stderr, "bbctape: execution address == %d\n", EXEC_ADDRESS);
  742.   
  743.   printf(" Opening file %s for output:\n", (char *)WAV_FILE);
  744.   audio = open((char *)WAV_FILE, O_WRONLY | O_CREAT, 0666); 
  745.   write_wav_header(audio);
  746.  
  747.   printf(" Opening file %s for input:\n", (char *)AUDIO_DEV);
  748.   data = open( (char *)AUDIO_DEV, O_RDONLY, 0); /* Open input data file */
  749.  
  750.   printf(" Writing data... \n");
  751.   save(data,audio);                     /* Call the func to do the work */
  752.   close(data);
  753.   close(audio);
  754. }
  755.  
  756. int main(int argc, char *argv[]){
  757.  
  758.   printf("\n\nDSP CODEC v0.01 starting...\n\n");
  759.   command = (u_char *)argv[0];
  760.   if (argc==1) usage();
  761.   if (strstr ((char *)command, "load")) bbc_load(argc,argv);
  762.   else if (strstr ((char *)command, "save")) bbc_save(argc,argv);
  763.   else {
  764.     fprintf (stderr,"Error: command should be named either bbc-load or bbc-save\n");
  765.     exit (1);
  766.   }
  767.   return 1;
  768. }
  769.   
  770.   
  771.  
  772.