?login_element?

Subversion Repositories NedoOS

Rev

Rev 366 | Blame | Compare with Previous | Last modification | View Log | Download

  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8.  
  9. #include "psg.h"
  10.  
  11.  
  12.  
  13.  
  14. struct psg_file * load_psg_file(char * filename)
  15. {
  16.         FILE * f = NULL;
  17.         struct psg_file * file = NULL;
  18.  
  19.         struct stat file_stat;
  20.  
  21.  
  22.         f = fopen(filename,"rb");
  23.         if( !f )
  24.         {
  25.                 fprintf(stderr,"Can't open file <%s>!\n",filename);
  26.                 goto ERROR;
  27.         }
  28.  
  29.         if( fstat(fileno(f),&file_stat) )
  30.         {
  31.                 fprintf(stderr,"Can't fstat file <%s>!\n",filename);
  32.                 goto ERROR;
  33.         }
  34.  
  35.         if( file_stat.st_size<=16 )
  36.         {
  37.                 fprintf(stderr,"File <%s> is too small!\n",filename);
  38.                 goto ERROR;
  39.         }
  40.  
  41.  
  42.         // allocate psg_file structure
  43.         file = malloc(sizeof(struct psg_file));
  44.         if( !file ) goto MEM_ERROR;
  45.         file->filename = NULL;
  46.         file->size = 0;
  47.         file->bytes = NULL;
  48.  
  49.         if( !(file->filename = malloc(1+strlen(filename))) ) goto MEM_ERROR;
  50.         strcpy(file->filename, filename);
  51.  
  52.         file->size = file_stat.st_size;
  53.  
  54.         if( !(file->bytes = malloc(file->size)) ) goto MEM_ERROR;
  55.  
  56.        
  57.         // load into allocated area
  58.         if( file->size != fread(file->bytes, 1, file->size, f) )
  59.         {
  60.                 fprintf(stderr,"Can't load from file <%s>!\n",filename);
  61.                 goto ERROR;
  62.         }
  63.  
  64.  
  65.         fclose(f);
  66.  
  67.         return file;
  68.  
  69.  
  70. /////////////////////////////////////////////////////////////////////
  71. MEM_ERROR:
  72.         fprintf(stderr,"%s: memory allocation error!\n",__PRETTY_FUNCTION__);
  73. ERROR:
  74.         free_psg_file(file);
  75.  
  76.         if( f ) fclose(f);
  77.         exit(1);
  78. }
  79.  
  80.  
  81.  
  82. void free_psg_file(struct psg_file * file)
  83. {
  84.         if( !file ) return;
  85.  
  86.         if( file->filename ) free(file->filename);
  87.         if( file->bytes )    free(file->bytes);
  88.  
  89.         free(file);
  90.  
  91.         return;
  92. }
  93.  
  94.  
  95.  
  96. int update_psg_regs(uint8_t * regs, struct psg_file * psg, size_t * position)
  97. { // updates regs[14] array with data from next PSG frame, if any.
  98.   // regs could be NULL (nothing is written then)
  99.   // psg_file * psg is a constant structure that contains data from psg file
  100.   // * position is current position into it, gets updated
  101.   //
  102.   // return values:
  103.   //  (-1): end of psg reached
  104.   //     0: run again until non-zero.
  105.   // any>0: regs[14] array is valid for the given amount of frame periods
  106.   //
  107.   // function makes exit(1) if PSG is incorrect
  108.   //
  109.   // always start running with *position=0 !
  110.   //
  111.  
  112.  
  113.         if( !position )
  114.         {
  115.                 fprintf(stderr,"%s: position pointer given is NULL!\n",__PRETTY_FUNCTION__);
  116.                 exit(1);
  117.         }
  118.         if( !psg )
  119.         {
  120.                 fprintf(stderr,"%s: struct psg_file pointer given is NULL!\n",__PRETTY_FUNCTION__);
  121.                 exit(1);
  122.         }
  123.         if( !psg->bytes )
  124.         {
  125.                 fprintf(stderr,"%s: bytes pointer in struct psg_file is NULL!\n",__PRETTY_FUNCTION__);
  126.                 exit(1);
  127.         }
  128.  
  129.  
  130.         // initialization
  131.         if( *position<16 )
  132.         {
  133.                 *position=16;
  134.  
  135.                 // init registers
  136.                 if( regs )
  137.                 {
  138.                         for(int i=0;i<14;i++) regs[i]=0;
  139.                 }
  140.  
  141.                 return 0; // rerun
  142.         }
  143.  
  144.         // EOF check by size
  145.         if( *position >= psg->size )
  146.         {
  147.                 return (-1);
  148.         }
  149.  
  150.         // EOF check by end mark
  151.         if( psg->bytes[*position] == 0xFD )
  152.         {
  153.                 return (-1);
  154.         }
  155.  
  156.         // prepare regs array
  157.         if( regs ) regs[13]=0xFF; // 0xFF means "DON'T WRITE to AY/YM"
  158.  
  159.         int frames=1;
  160.         int was_delimiter=0;
  161.         for(;;)
  162.         {
  163.                 if( !(psg->bytes[*position] & 0xF0) )
  164.                 { // register contents
  165.                         if( was_delimiter )
  166.                         { // parse next frame in next iteration
  167.                                 return frames;
  168.                         }
  169.  
  170.                         uint8_t reg_num = psg->bytes[(*position)++];
  171.  
  172.                         if( *position >= psg->size )
  173.                         {
  174.                                 fprintf(stderr,"%s: error in PSG format at the offset 0x%lx!",__PRETTY_FUNCTION__,(*position)-1);
  175.                                 exit(1);
  176.                         }
  177.  
  178.                         uint8_t reg_value = psg->bytes[(*position)++];
  179.  
  180.                         if( regs && reg_num<14 ) regs[reg_num]=reg_value;
  181.                        
  182.                         if( *position >= psg->size ) return frames;
  183.                 }
  184.                 else if( psg->bytes[*position]==0xFD )
  185.                 { // end mark -- will be parsed on next iteration. *position is NOT incremented!
  186.                         return frames;
  187.                 }
  188.                 else if( psg->bytes[*position]==0xFF )
  189.                 { // 1-frame delimiter
  190.                         if( was_delimiter )
  191.                                 frames++;
  192.                         else
  193.                                 was_delimiter = 1;
  194.                        
  195.                         (*position)++;
  196.                         if( *position >= psg->size ) return frames;
  197.                 }
  198.                 else if( psg->bytes[*position]==0xFE )
  199.                 { // pause in 4-frame increments
  200.                         (*position)++;
  201.                         if( *position >= psg->size )
  202.                         {
  203.                                 fprintf(stderr,"%s: error in PSG format at the offset 0x%lx!",__PRETTY_FUNCTION__,(*position)-1);
  204.                                 exit(1);
  205.                         }
  206.  
  207.                         int num_frames = 4*(psg->bytes[*position]);
  208.  
  209.                         if( !was_delimiter )
  210.                         {
  211.                                 num_frames--;
  212.                                 was_delimiter=1;
  213.                         }
  214.  
  215.                         frames += num_frames;
  216.  
  217.                         (*position)++;
  218.                         if( *position >= psg->size ) return frames;
  219.                 }
  220.                 else
  221.                 {
  222.                         fprintf(stderr,"%s: error in PSG format at the offset 0x%lx!",__PRETTY_FUNCTION__,*position);
  223.                         exit(1);
  224.                 }
  225.         }
  226. }
  227.  
  228.  
  229.  
  230.  
  231. struct frame_list * build_psg_frames(struct psg_file * psg)
  232. {
  233.         struct frame_list * head = NULL;
  234.        
  235.         struct frame_list * local_head = NULL;
  236.  
  237.  
  238.  
  239.         size_t position;
  240.         int frames_spent;
  241.  
  242.         uint8_t regs[14];
  243.  
  244.  
  245.  
  246. //      // first count number of frames
  247. //      frames = 0;
  248. //      position = 0;
  249. //      //
  250. //      while( (curr_frames=update_psg_regs(NULL,psg,&position)) >= 0 )
  251. //              frames +=curr_frames;
  252. //
  253.  
  254.         // build frame list
  255.         position = 0;
  256.         while( (frames_spent=update_psg_regs(regs,psg,&position)) >= 0 )
  257.         {
  258.                 if( frames_spent==0 ) continue;
  259.  
  260.                 // create frame_ay structure
  261.                 struct frame_ay * ay_regs = malloc(sizeof(struct frame_ay));
  262.                 if( !ay_regs ) goto MEM_ERROR;
  263.  
  264.                 ay_regs->base.type = FRAME_AY;
  265.                 memcpy(ay_regs->regs,regs,14);
  266.  
  267.                 // add frames_spent list elements pointing to this structure to the local list
  268.                 //
  269.                 for(int i=0;i<frames_spent;i++)
  270.                 {
  271.                         struct frame_list * element = malloc(sizeof(struct frame_list));
  272.                         if( !element ) goto MEM_ERROR;
  273.  
  274.                         element->frame = (struct frame_base *)ay_regs;
  275.  
  276.                         element->next = local_head;
  277.                         local_head = element;
  278.                 }
  279.         }
  280.  
  281.         // reverse local_head-based list into global head-pointed list
  282.         if( local_head )
  283.         {
  284.                 do
  285.                 {
  286.                         struct frame_list * old_next = local_head->next;
  287.  
  288.                         local_head->next = head;
  289.                         head = local_head;
  290.  
  291.                         local_head = old_next;
  292.  
  293.                 } while( local_head );
  294.         }
  295.         else
  296.         { // were no frames -- PSG format error
  297.                 fprintf(stderr,"%s: error in PSG format: no frames found!",__PRETTY_FUNCTION__);
  298.                 goto ERROR;
  299.         }
  300.  
  301.  
  302.  
  303.         return head;
  304.  
  305.  
  306.  
  307. MEM_ERROR:
  308.         fprintf(stderr,"%s: memory allocation error!\n",__PRETTY_FUNCTION__);
  309. ERROR:
  310.         free_psg_frames(local_head);
  311.         free_psg_frames(head);
  312.  
  313.         exit(1);
  314. }
  315.  
  316.  
  317.  
  318.  
  319. void free_psg_frames(struct frame_list * head)
  320. {
  321.         struct frame_base * oldframe = NULL;
  322.         struct frame_list * freeme;
  323.  
  324.         while( head )
  325.         {
  326.                 if( head->frame )
  327.                 {
  328.                         if( oldframe != head->frame )
  329.                         {
  330.                                 oldframe = head->frame;
  331.                                 free(oldframe);
  332.                         }
  333.                 }
  334.  
  335.                 freeme = head;
  336.                 head = head->next;
  337.  
  338.                 free(freeme);
  339.         }
  340. }
  341.  
  342.