Exemplo n.º 1
0
/* debug util, mainly for custom IO testing */
void dump_streamfile(STREAMFILE *streamFile, const char* out) {
#ifdef VGM_DEBUG_OUTPUT
    off_t offset = 0;
    FILE *f = NULL;

    if (out) {
        f = fopen(out,"wb");
        if (!f) return;
    }

    VGM_LOG("dump streamfile, size: %x\n", get_streamfile_size(streamFile));
    while (offset < get_streamfile_size(streamFile)) {
        uint8_t buffer[0x8000];
        size_t read;

        read = read_streamfile(buffer,offset,0x8000,streamFile);
        if (out)
            fwrite(buffer,sizeof(uint8_t),read, f);
        else
            VGM_LOGB(buffer,read,0);
        offset += read;
    }

    if (out) {
        fclose(f);
    }
#endif
}
Exemplo n.º 2
0
static STREAMFILE* setup_bgw_atrac3_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, size_t frame_size, int channels) {
    STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
    bgw_decryption_data io_data = {0};
    size_t io_data_size = sizeof(bgw_decryption_data);
    int ch;

    /* setup decryption with key (first frame + modified channel header) */
    if (frame_size*channels == 0 || frame_size*channels > BGW_KEY_MAX) goto fail;

    io_data.key_size = read_streamfile(io_data.key, subfile_offset, frame_size*channels, streamFile);
    for (ch = 0; ch < channels; ch++) {
        uint32_t xor = get_32bitBE(io_data.key + frame_size*ch);
        put_32bitBE(io_data.key + frame_size*ch, xor ^ 0xA0024E9F);
    }

    /* setup subfile */
    new_streamFile = open_wrap_streamfile(streamFile);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, bgw_decryption_read,NULL);
    if (!new_streamFile) goto fail;
    temp_streamFile = new_streamFile;

    return temp_streamFile;

fail:
    close_streamfile(temp_streamFile);
    return NULL;
}
Exemplo n.º 3
0
static size_t read_func_um3(void *ptr, size_t size, size_t nmemb, void * datasource)
{
    ogg_vorbis_streamfile * const ov_streamfile = datasource;
    size_t items_read;

    size_t bytes_read;
   
    bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb,
            ov_streamfile->streamfile);

    items_read = bytes_read / size;

    /* first 0x800 bytes of um3 are xor'd with 0xff */
    if (ov_streamfile->offset < 0x800) {
        int num_crypt = 0x800-ov_streamfile->offset;
        int i;

        if (num_crypt > bytes_read) num_crypt=bytes_read;
        for (i=0;i<num_crypt;i++)
            ((uint8_t*)ptr)[i] ^= 0xff;
    }

    ov_streamfile->offset += items_read * size;

    return items_read;
}
Exemplo n.º 4
0
static size_t read_func_scd(void *ptr, size_t size, size_t nmemb, void * datasource)
{
    ogg_vorbis_streamfile * const ov_streamfile = datasource;
    size_t items_read;

    size_t bytes_read;
   
    bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb,
            ov_streamfile->streamfile);

    items_read = bytes_read / size;

    /* first bytes are xor'd with a constant byte */
    if (ov_streamfile->offset < ov_streamfile->scd_xor_len) {
        int num_crypt = ov_streamfile->scd_xor_len-ov_streamfile->offset;
        int i;

        if (num_crypt > bytes_read) num_crypt=bytes_read;
        for (i=0;i<num_crypt;i++)
            ((uint8_t*)ptr)[i] ^= ov_streamfile->scd_xor;
    }

    ov_streamfile->offset += items_read * size;

    return items_read;
}
Exemplo n.º 5
0
static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length)
{
    size_t sz = 0;

    while (length > 0)
    {
        off_t to_read;
        off_t length_available;
        off_t block_num;
        off_t intrablock_offset;
        off_t physical_offset;


        block_num = offset / streamfile->interleave_block_size;
        intrablock_offset = offset % streamfile->interleave_block_size;
        streamfile->current_logical_offset = offset;
        physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset;

        length_available =
                streamfile->interleave_block_size - intrablock_offset;

        if (length < length_available)
        {
            to_read = length;
        }
        else
        {
            to_read = length_available;
        }

        if (to_read > 0)
        {
            size_t bytes_read;

            bytes_read = read_streamfile(dest,
                physical_offset,
                to_read, streamfile->real_file);

            sz += bytes_read;

            streamfile->current_logical_offset = offset + bytes_read;

            if (bytes_read != to_read)
            {
                /* an error which we will not attempt to handle here */
                return sz;
            }

            dest += bytes_read;
            offset += bytes_read;
            length -= bytes_read;
        }
    }

    return sz;
}
Exemplo n.º 6
0
static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
  /* truncate at end of logical file */
  if (offset+length > streamfile->file_size)
  {
      long signed_length = length;
      signed_length = streamfile->file_size - offset;
      if (signed_length < 0) signed_length = 0;
      length = signed_length;
  }
  return read_streamfile(dest,
          streamfile->start_physical_offset+offset,
          length,streamfile->real_file);
}
Exemplo n.º 7
0
static size_t read_func(void *ptr, size_t size, size_t nmemb, void * datasource)
{
    ogg_vorbis_streamfile * const ov_streamfile = datasource;
    size_t items_read;

    size_t bytes_read;
   
    bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb,
            ov_streamfile->streamfile);

    items_read = bytes_read / size;

    ov_streamfile->offset += items_read * size;

    return items_read;
}
Exemplo n.º 8
0
void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
    VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
    g719_codec_data *data = vgmstream->codec_data;
    g719_codec_data *ch_data = &data[channel];
    int i;

    if (0 == vgmstream->samples_into_block) {
        int16_t code_buffer[G719_MAX_CODES];

        read_streamfile((uint8_t*)code_buffer, ch->offset, vgmstream->interleave_block_size, ch->streamfile);
        g719_decode_frame(ch_data->handle, code_buffer, ch_data->buffer);
    }

    for (i = 0; i < samples_to_do; i++) {
        outbuf[i*channelspacing] = ch_data->buffer[vgmstream->samples_into_block+i];
    }
}
Exemplo n.º 9
0
static size_t read_func_psych(void *ptr, size_t size, size_t nmemb, void * datasource)
{
    ogg_vorbis_streamfile * const ov_streamfile = datasource;
    size_t items_read;

    size_t bytes_read;
    size_t i;
   
    bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb,
            ov_streamfile->streamfile);

    /* add 0x23 ('#') */
    for (i=0;i<bytes_read;i++)
        ((uint8_t*)ptr)[i] += 0x23;

    items_read = bytes_read / size;

    ov_streamfile->offset += items_read * size;

    return items_read;
}
Exemplo n.º 10
0
/* decode anything mpg123 can */
void decode_mpeg(VGMSTREAMCHANNEL *stream,
        mpeg_codec_data * data,
        sample * outbuf, int32_t samples_to_do, int channels) {
    int samples_done = 0;

    while (samples_done < samples_to_do) {
        size_t bytes_done;
        int rc;

        if (!data->buffer_full) {
            data->bytes_in_buffer = read_streamfile(data->buffer,
                    stream->offset,MPEG_BUFFER_SIZE,stream->streamfile);

            data->buffer_full = 1;
            data->buffer_used = 0;

            stream->offset += data->bytes_in_buffer;
        }

        if (!data->buffer_used) {
            rc = mpg123_decode(data->m,
                    data->buffer,data->bytes_in_buffer,
                    (unsigned char *)(outbuf+samples_done*channels),
                    (samples_to_do-samples_done)*sizeof(sample)*channels,
                    &bytes_done);
            data->buffer_used = 1;
        } else {
            rc = mpg123_decode(data->m,
                    NULL,0,
                    (unsigned char *)(outbuf+samples_done*channels),
                    (samples_to_do-samples_done)*sizeof(sample)*channels,
                    &bytes_done);
        }

        if (rc == MPG123_NEED_MORE) data->buffer_full = 0;

        samples_done += bytes_done/sizeof(sample)/channels;
    }
}
Exemplo n.º 11
0
static size_t read_func_kovs(void *ptr, size_t size, size_t nmemb, void * datasource)
{
    ogg_vorbis_streamfile * const ov_streamfile = datasource;
    size_t items_read;

    size_t bytes_read;
   
    bytes_read = read_streamfile(ptr, ov_streamfile->offset+ov_streamfile->other_header_bytes, size * nmemb,
            ov_streamfile->streamfile);

    items_read = bytes_read / size;

    /* first 0x100 bytes of KOVS are xor'd with offset */
    if (ov_streamfile->offset < 0x100) {
        int i;

        for (i=ov_streamfile->offset;i<0x100;i++)
            ((uint8_t*)ptr)[i-ov_streamfile->offset] ^= i;
    }

    ov_streamfile->offset += items_read * size;

    return items_read;
}
Exemplo n.º 12
0
/**
 * open file containing looping data and copy to buffer
 *
 * returns true if found and copied
 */
int read_pos_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile) {
    char posname[PATH_LIMIT];
    char filename[PATH_LIMIT];
    /*size_t bytes_read;*/
    STREAMFILE * streamFilePos= NULL;

    streamFile->get_name(streamFile,filename,sizeof(filename));

    if (strlen(filename)+4 > sizeof(posname)) goto fail;

    /* try to open a posfile using variations: "(name.ext).pos" */
    {
        strcpy(posname, filename);
        strcat(posname, ".pos");
        streamFilePos = streamFile->open(streamFile,posname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFilePos) goto found;

        goto fail;
    }

found:
    //if (get_streamfile_size(streamFilePos) != bufsize) goto fail;

    /* allow pos files to be of different sizes in case of new features, just fill all we can */
    memset(buf, 0, bufsize);
    read_streamfile(buf, 0, bufsize, streamFilePos);

    close_streamfile(streamFilePos);

    return 1;

fail:
    if (streamFilePos) close_streamfile(streamFilePos);

    return 0;
}
Exemplo n.º 13
0
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
  size_t sz = 0;

  /*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
  while (length > 0)
  {
      int read_something = 0;

      /* read the beginning of the requested block, if we can */
      if (offset >= streamfile->current_logical_offset)
      {
          off_t to_read;
          off_t length_available;

          length_available = 
              (streamfile->current_logical_offset+
               streamfile->current_block_size) - 
              offset;

          if (length < length_available)
          {
              to_read = length;
          }
          else
          {
              to_read = length_available;
          }

          if (to_read > 0)
          {
              size_t bytes_read;

              bytes_read = read_streamfile(dest,
                      streamfile->current_physical_offset+0x10+
                          (offset-streamfile->current_logical_offset),
                      to_read,streamfile->real_file);

              sz += bytes_read;
              if (bytes_read != to_read)
              {
                  /* an error which we will not attempt to handle here */
                  return sz;
              }

              read_something = 1;

              dest += bytes_read;
              offset += bytes_read;
              length -= bytes_read;
          }
      }

      if (!read_something)
      {
          /* couldn't read anything, must seek */
          int found_block = 0;

          /* as we have no memory we must start seeking from the beginning */
          if (offset < streamfile->current_logical_offset)
          {
              streamfile->current_logical_offset = 0;
              streamfile->current_block_size = 0;
              streamfile->current_physical_offset = 
                  streamfile->start_physical_offset;
          }

          /* seek ye forwards */
          while (!found_block) {
              /*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
              switch (read_32bitBE(streamfile->current_physical_offset,
                          streamfile->real_file))
              {
                  case 0x41495850:  /* AIXP */
                      if (read_8bit(
                                  streamfile->current_physical_offset+8,
                                  streamfile->real_file) ==
                              streamfile->stream_id)
                      {
                          streamfile->current_block_size =
                              (uint16_t)read_16bitBE(
                                  streamfile->current_physical_offset+0x0a,
                                  streamfile->real_file);

                          if (offset >= streamfile->current_logical_offset+
                                  streamfile->current_block_size)
                          {
                              streamfile->current_logical_offset +=
                                  streamfile->current_block_size;
                          }
                          else
                          {
                              found_block = 1;
                          }
                      }

                      if (!found_block)
                      {
                          streamfile->current_physical_offset +=
                              read_32bitBE(
                                      streamfile->current_physical_offset+0x04,
                                      streamfile->real_file
                                      ) + 8;
                      }

                      break;
                  case 0x41495846:  /* AIXF */
                      /* shouldn't ever see this */
                  case 0x41495845:  /* AIXE */
                      /* shouldn't have reached the end o' the line... */
                  default:
                      return sz;
                      break;
              } /* end block/chunk type select */
          } /* end while !found_block */
      } /* end if !read_something */
  } /* end while length > 0 */
  
  return sz;
}
Exemplo n.º 14
0
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
 * actually vary and are much shorter */
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
        mpeg_codec_data * data,
        sample * outbuf, int32_t samples_to_do) {
    int samples_done = 0;

    while (samples_done < samples_to_do) {
        size_t bytes_done;
        int rc;

        if (!data->buffer_full) {
            /* fill buffer up to next frame ending (or file ending) */
            int bytes_into_header = 0;
            const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
            off_t frame_offset = 0;

            /* assume that we are starting at a header, skip it and look for the
             * next one */
            read_streamfile(data->buffer, stream->offset+frame_offset, 4,
                    stream->streamfile);
            frame_offset += 4;

            do {
                uint8_t byte;
                byte =
                    read_8bit(stream->offset+frame_offset,stream->streamfile);
                data->buffer[frame_offset] = byte;
                frame_offset++;

                if (byte == header[bytes_into_header]) {
                    bytes_into_header++;
                } else {
                    /* This might have been the first byte of the header, so
                     * we need to check again.
                     * No need to get more complicated than this, though, since
                     * there are no repeated characters in the search string. */
                    if (bytes_into_header>0) {
                        frame_offset--;
                    }
                    bytes_into_header=0;
                }

                if (bytes_into_header==4) {
                    break;
                }
            } while (frame_offset < AHX_EXPECTED_FRAME_SIZE);

            if (bytes_into_header==4) frame_offset-=4;
            memset(data->buffer+frame_offset,0,
                    AHX_EXPECTED_FRAME_SIZE-frame_offset);

            data->buffer_full = 1;
            data->buffer_used = 0;

            stream->offset += frame_offset;
        }

        if (!data->buffer_used) {
            rc = mpg123_decode(data->m,
                    data->buffer,AHX_EXPECTED_FRAME_SIZE,
                    (unsigned char *)(outbuf+samples_done),
                    (samples_to_do-samples_done)*sizeof(sample),
                    &bytes_done);
            data->buffer_used = 1;
        } else {
            rc = mpg123_decode(data->m,
                    NULL,0,
                    (unsigned char *)(outbuf+samples_done),
                    (samples_to_do-samples_done)*sizeof(sample),
                    &bytes_done);
        }

        if (rc == MPG123_NEED_MORE) data->buffer_full = 0;

        samples_done += bytes_done/sizeof(sample);
    }
}
Exemplo n.º 15
0
/* Convers custom Opus packets to Ogg Opus, so the resulting data is larger than physical data. */
static size_t opus_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, opus_io_data* data) {
    size_t total_read = 0;

    /* ignore bad reads */
    if (offset < 0 || offset > data->logical_size) {
        return total_read;
    }

    /* previous offset: re-start as we can't map logical<>physical offsets */
    if (offset < data->logical_offset) {
        data->physical_offset = data->stream_offset;
        data->logical_offset = 0x00;
        data->page_size = 0;
        data->samples_done = 0;
        data->sequence = 2; /* appended header is 0/1 */

        if (offset >= data->head_size)
            data->logical_offset = data->head_size;
    }

    /* insert fake header */
    if (offset < data->head_size) {
        size_t bytes_consumed, to_read;

        bytes_consumed = offset - data->logical_offset;
        to_read = data->head_size - bytes_consumed;
        if (to_read > length)
            to_read = length;
        memcpy(dest, data->head_buffer + bytes_consumed, to_read);

        total_read += to_read;
        dest += to_read;
        offset += to_read;
        length -= to_read;
        data->logical_offset += to_read;
    }

    /* read blocks, one at a time */
    while (length > 0) {

        /* ignore EOF */
        if (data->logical_offset >= data->logical_size) {
            break;
        }

        /* process new block */
        if (data->page_size == 0) {
            size_t data_size, skip_size, oggs_size;

            switch(data->type) {
                case OPUS_SWITCH: /* format seem to come from opus_test and not Nintendo-specific */
                    data_size = read_32bitBE(data->physical_offset, streamfile);
                    skip_size = 0x08; /* size + Opus state(?) */
                    break;
                case OPUS_UE4:
                    data_size = (uint16_t)read_16bitLE(data->physical_offset, streamfile);
                    skip_size = 0x02;
                    break;
                case OPUS_EA:
                    data_size = (uint16_t)read_16bitBE(data->physical_offset, streamfile);
                    skip_size = 0x02;
                    break;
                case OPUS_X:
                    data_size = get_xopus_packet_size(data->sequence - 2, streamfile);
                    skip_size = 0;
                    break;
                default:
                    return 0;
            }

            oggs_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */

            data->block_size = data_size + skip_size;
            data->page_size = oggs_size + data_size;

            if (data->page_size > sizeof(data->page_buffer)) { /* happens on bad reads/EOF too */
                VGM_LOG("OPUS: buffer can't hold OggS at %x\n", (uint32_t)data->physical_offset);
                data->page_size = 0;
                break;
            }

            /* create fake OggS page (full page for checksums) */
            read_streamfile(data->page_buffer+oggs_size, data->physical_offset + skip_size, data_size, streamfile); /* store page data */
            data->samples_done += opus_get_packet_samples(data->page_buffer+oggs_size, data_size);
            make_oggs_page(data->page_buffer,sizeof(data->page_buffer), data_size, data->sequence, data->samples_done);
            data->sequence++;
        }

        /* move to next block */
        if (offset >= data->logical_offset + data->page_size) {
            data->physical_offset += data->block_size;
            data->logical_offset += data->page_size;
            data->page_size = 0;
            continue;
        }

        /* read data */
        {
            size_t bytes_consumed, to_read;

            bytes_consumed = offset - data->logical_offset;
            to_read = data->page_size - bytes_consumed;
            if (to_read > length)
                to_read = length;
            memcpy(dest, data->page_buffer + bytes_consumed, to_read);

            total_read += to_read;
            dest += to_read;
            offset += to_read;
            length -= to_read;

            if (to_read == 0) {
                break; /* error/EOF */
            }
        }
    }

    return total_read;
}
Exemplo n.º 16
0
/* return 0 if not found, 1 if found and set parameters */
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add)
{
    uint16_t * scales = NULL;
    uint16_t * prescales = NULL;
    int bruteframe=0,bruteframecount=-1;
    int startoff, endoff;
    int rc = 0;

    startoff=read_16bitBE(2, file)+4;
    endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff;

    /* how many scales? */
    {
        int framecount=(endoff-startoff)/18;
        if (framecount<bruteframecount || bruteframecount<0)
            bruteframecount=framecount;
    }

    /* find longest run of nonzero frames */
    {
        int longest=-1,longest_length=-1;
        int i;
        int length=0;
        for (i=0;i<bruteframecount;i++) {
            static const unsigned char zeroes[18]={0};
            unsigned char buf[18];
            read_streamfile(buf, startoff+i*18, 18, file);
            if (memcmp(zeroes,buf,18)) length++;
            else length=0;
            if (length > longest_length) {
                longest_length=length;
                longest=i-length+1;
                if (longest_length >= 0x8000) break;
            }
        }
        if (longest==-1) {
            goto find_key_cleanup;
        }
        bruteframecount = longest_length;
        bruteframe = longest;
    }

    {
        /* try to guess key */
#define MAX_FRAMES (INT_MAX/0x8000)
        int scales_to_do;
        int key_id;

        /* allocate storage for scales */
        scales_to_do = (bruteframecount > MAX_FRAMES ? MAX_FRAMES : bruteframecount);
        scales = malloc(scales_to_do*sizeof(uint16_t));
        if (!scales) {
            goto find_key_cleanup;
        }
        /* prescales are those scales before the first frame we test
         * against, we use these to compute the actual start */
        if (bruteframe > 0) {
            int i;
            /* allocate memory for the prescales */
            prescales = malloc(bruteframe*sizeof(uint16_t));
            if (!prescales) {
                goto find_key_cleanup;
            }
            /* read the prescales */
            for (i=0; i<bruteframe; i++) {
                prescales[i] = read_16bitBE(startoff+i*18, file);
            }
        }

        /* read in the scales */
        {
            int i;
            for (i=0; i < scales_to_do; i++) {
                scales[i] = read_16bitBE(startoff+(bruteframe+i)*18, file);
            }
        }

        if (type == 8)
        {
            /* guess each of the keys */
            for (key_id=0;key_id<keys_8_count;key_id++) {
                /* test pre-scales */
                uint16_t xor = keys_8[key_id].start;
                uint16_t mult = keys_8[key_id].mult;
                uint16_t add = keys_8[key_id].add;
                int i;

                for (i=0;i<bruteframe &&
                        ((prescales[i]&0x6000)==(xor&0x6000) ||
                         prescales[i]==0);
                        i++) {
                    xor = xor * mult + add;
                }

                if (i == bruteframe)
                {
                    /* test */
                    for (i=0;i<scales_to_do &&
                            (scales[i]&0x6000)==(xor&0x6000);i++) {
                        xor = xor * mult + add;
                    }
                    if (i == scales_to_do)
                    {
                        *xor_start = keys_8[key_id].start;
                        *xor_mult = keys_8[key_id].mult;
                        *xor_add = keys_8[key_id].add;

                        rc = 1;
                        goto find_key_cleanup;
                    }
                }
            }
        }
        else if (type == 9)
        {
            /* smarter XOR as seen in PSO2, can't do an exact match so we
             * have to search for the lowest */
            long best_score = MAX_FRAMES * 0x1fff;

            /* guess each of the keys */
            for (key_id=0;key_id<keys_9_count;key_id++) {
                /* run past pre-scales */
                uint16_t xor = keys_9[key_id].start;
                uint16_t mult = keys_9[key_id].mult;
                uint16_t add = keys_9[key_id].add;
                int i;
                long total_score = 0;

                for (i=0;i<bruteframe;i++) {
                    xor = xor * mult + add;
                }

                if (i == bruteframe)
                {
                    /* test */
                    for (i=0;i<scales_to_do && total_score < best_score;i++) {
                        xor = xor * mult + add;
                        total_score += (scales[i]^xor)&0x1fff;
                    }

                    if (total_score < best_score)
                    {
                        *xor_start = keys_9[key_id].start;
                        *xor_mult = keys_9[key_id].mult;
                        *xor_add = keys_9[key_id].add;

                        best_score = total_score;
                    }
                }
            }

            /* arbitrarily decide if we have won? */
            if (best_score < scales_to_do * 0x1000)
            {
                rc = 1;
            }
        }
    }

find_key_cleanup:
    if (scales) free(scales);
    if (prescales) free(prescales);
    return rc;
}
VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
	
	// used for loop points ...
	uint8_t eofVAG[16]={0x00,0x07,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77};
	uint8_t eofVAG2[16]={0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	uint8_t readbuf[16];

	off_t readOffset = 0x20;

	off_t loopStart = 0;
	off_t loopEnd = 0;

	uint8_t	vagID;
	off_t start_offset;
	size_t fileLength;

	size_t interleave;
	
    int loop_flag=0;
    int channel_count=1;
    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("vag",filename_extension(filename))) goto fail;

    /* check VAG Header */
    if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && 
 		((read_32bitLE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700))
        goto fail;

	/* Check for correct channel count */
	vagID=read_8bit(0x03,streamFile);

	switch(vagID) {
		case 'i':
			channel_count=2;
			break;
		case 'V':
			if(read_32bitBE(0x20,streamFile)==0x53746572) // vag Stereo
				channel_count=2;
		case 'p':
			if((read_32bitBE(0x04,streamFile)<=0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) {
				loop_flag=(read_32bitBE(0x14,streamFile)!=0);
				channel_count=2;
			} else {
				/* Search for loop in VAG */
				fileLength = get_streamfile_size(streamFile);
				
				do {
					readOffset+=0x10; 
					
					// Loop Start ...
					if(read_8bit(readOffset+0x01,streamFile)==0x06) {
						if(loopStart==0) loopStart = readOffset;
					}

					// Loop End ...
					if(read_8bit(readOffset+0x01,streamFile)==0x03) {
						if(loopEnd==0) loopEnd = readOffset;
					}

					// Loop from end to beginning ...
					if((read_8bit(readOffset+0x01,streamFile)==0x01)) {
						// Check if we have the eof tag after the loop point ...
						// if so we don't loop, if not present, we loop from end to start ...
						read_streamfile(readbuf,readOffset+0x10,0x10,streamFile);
						if((readbuf[0]!=0) && (readbuf[0]!=0x0c)) {
							if(memcmp(readbuf,eofVAG,0x10) && (memcmp(readbuf,eofVAG2,0x10))) {
								loopStart = 0x40;
								loopEnd = readOffset;
							}
						}
					}

				} while (streamFile->get_offset(streamFile)<(off_t)fileLength);
				loop_flag = (loopEnd!=0);
			}
			break;
        default:
            goto fail;
	}

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->channels = channel_count;

	switch(vagID) {
		case 'i': // VAGi
			vgmstream->layout_type=layout_interleave;
			vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
			vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28;
			interleave = read_32bitLE(0x08,streamFile);
			vgmstream->meta_type=meta_PS2_VAGi;
			start_offset=0x800;
			break;
		case 'p': // VAGp
			vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
			interleave=0x10; // used for loop calc

			if((read_32bitBE(0x04,streamFile)==0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) {
				vgmstream->channels=2;
				vgmstream->num_samples = read_32bitBE(0x0C,streamFile);

				if(loop_flag) {
					vgmstream->loop_start_sample=read_32bitBE(0x14,streamFile);
					vgmstream->loop_end_sample =read_32bitBE(0x18,streamFile);
				}

				start_offset=0x80;
				vgmstream->layout_type=layout_interleave;
				vgmstream->meta_type=meta_PS2_VAGs;

				// Double VAG Header @ 0x0000 & 0x1000
				if(read_32bitBE(0,streamFile)==read_32bitBE(0x1000,streamFile)) {
					vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28;
					interleave=0x1000;
					start_offset=0;
				}

			} else {
				vgmstream->layout_type=layout_none;
				vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28;
				vgmstream->meta_type=meta_PS2_VAGp;
				start_offset=0x30;
			}
			break;
		case 'V': // pGAV
			vgmstream->layout_type=layout_interleave;
			interleave=0x2000;

			// Jak X hack ...
			if(read_32bitLE(0x1000,streamFile)==0x56414770)
				interleave=0x1000;

			vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
			vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*14;
			vgmstream->meta_type=meta_PS2_pGAV;
			start_offset=0;
			break;
        default:
            goto fail;
	}

	vgmstream->interleave_block_size=interleave;
	
	/* Don't add the header size to loop calc points */
	if(vgmstream->meta_type!=meta_PS2_VAGs) {
		loopStart-=start_offset;
		loopEnd-=start_offset;

		if(loop_flag!=0) {
			vgmstream->loop_start_sample = (int32_t)((loopStart/(interleave*channel_count))*interleave)/16*28;
			vgmstream->loop_start_sample += (int32_t)(loopStart%(interleave*channel_count))/16*28;
			vgmstream->loop_end_sample = (int32_t)((loopEnd/(interleave*channel_count))*interleave)/16*28;
			vgmstream->loop_end_sample += (int32_t)(loopEnd%(interleave*channel_count))/16*28;
		}
	}

    /* Compression Scheme */
    vgmstream->coding_type = coding_PSX;

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                (off_t)(start_offset+vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 18
0
VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];
    int channel_count;
    int loop_flag=0;
	char little_endian=0;
	off_t	start_offset;
	EACSHeader	*ea_header = NULL;
	int32_t samples_count=0;
    int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("cnk",filename_extension(filename)) && 
		strcasecmp("as4",filename_extension(filename)) && 
		strcasecmp("asf",filename_extension(filename))) goto fail;

	ea_header=(EACSHeader *)malloc(sizeof(EACSHeader));

    /* check header */
    if ((uint32_t)read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */
        goto fail;

	/* check if we are little or big endian */
    if ((uint32_t)read_32bitBE(4,streamFile)<0x40) 
        little_endian=1;

    /* check type details */
	start_offset = read_32bitLE(0x04,streamFile);

	if((uint32_t)read_32bitBE(0x08,streamFile)==0x45414353) { /* EACS */ 
		read_streamfile((uint8_t*)ea_header,0x08,sizeof(EACSHeader),streamFile);
		loop_flag = 0; //(ea_header->dwLoopStart!=0);
		channel_count = (ea_header->bChannels);
		/* build the VGMSTREAM */

		vgmstream = allocate_vgmstream(channel_count,0);
		if (!vgmstream) goto fail;

		/* fill in the vital statistics */
		init_get_high_nibble(vgmstream);
		
		vgmstream->sample_rate = ea_header->dwSampleRate;
		
		if(ea_header->bCompression==0) {
			vgmstream->coding_type = coding_PCM16LE_int;
			if(ea_header->bBits==1)
				vgmstream->coding_type = coding_PCM8_int;
		}
		else 
			vgmstream->coding_type = coding_EACS_IMA;
		
		vgmstream->layout_type = layout_eacs_blocked;
		vgmstream->meta_type = meta_EACS_PC;

		if(little_endian)
			vgmstream->meta_type = meta_EACS_SAT;

	} else {
		channel_count=read_32bitLE(0x20,streamFile);
		
		vgmstream = allocate_vgmstream(channel_count,0);
		if (!vgmstream) goto fail;

		vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
		vgmstream->coding_type = coding_PSX;
		vgmstream->layout_type=layout_eacs_blocked;
		vgmstream->meta_type=meta_EACS_PSX;
	}

	vgmstream->ea_platform=little_endian;

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
            if (!vgmstream->ch[i].streamfile) goto fail;
        }
    }

	// calc the samples length ...
	if(little_endian)
		vgmstream->next_block_offset=read_32bitBE(0x04,streamFile);
	else
		vgmstream->next_block_offset=read_32bitLE(0x04,streamFile);

	if(vgmstream->next_block_offset>0x30) {
		vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader);
		samples_count=(int32_t)vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream);
		samples_count/=vgmstream->channels;
	}
	
	do {
		if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) {
			ea_header->dwLoopStart=read_32bitLE(vgmstream->next_block_offset+0x08,vgmstream->ch[0].streamfile);
			vgmstream->next_block_offset+=0x0C;
		}

		if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E65) 
			break;

		eacs_block_update(vgmstream->next_block_offset,vgmstream);
		samples_count+=vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream);
	} while(vgmstream->next_block_offset<get_streamfile_size(streamFile)-8);

	// Reset values ...
	// setting up the first header by calling the eacs_block_update sub
	if(little_endian)
		vgmstream->next_block_offset=read_32bitBE(0x04,streamFile);
	else
		vgmstream->next_block_offset=read_32bitLE(0x04,streamFile);

	vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader);
	
	if(vgmstream->coding_type!=coding_PSX)
		vgmstream->current_block_size-=8;

	if(vgmstream->coding_type==coding_PSX) 
		eacs_block_update(0x2C,vgmstream);
	else 
		eacs_block_update(0x28,vgmstream);

	// re-allocate the sample count
	vgmstream->num_samples=samples_count;
	
	if(loop_flag) {
		vgmstream->loop_start_sample = ea_header->dwLoopStart;
		vgmstream->loop_end_sample = vgmstream->num_samples;
	}

	if(ea_header) 
		free(ea_header);

    return vgmstream;

    /* clean up anything we may have opened */
fail:
	if(ea_header) 
		free(ea_header);
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 19
0
/* loop points have been found hiding here */
void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE  *streamFile,
        long *loop_start, long *loop_end, int *loop_flag) {
    int loop_start_found = 0;
    int loop_end_found = 0;

    off_t current_chunk = adtl_offset+4;

    while (current_chunk < adtl_offset+adtl_length) {
        uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
        off_t chunk_size = read_32bitLE(current_chunk+4,streamFile);

        if (current_chunk+8+chunk_size > adtl_offset+adtl_length) return;

        switch(chunk_type) {
            case 0x6c61626c:    /* labl */
                {
                    unsigned char *labelcontent;
                    labelcontent = malloc(chunk_size-4);
                    if (!labelcontent) return;
                    if (read_streamfile(labelcontent,current_chunk+0xc,
                                chunk_size-4,streamFile)!=chunk_size-4) {
                        free(labelcontent);
                        return;
                    }

                    switch (read_32bitLE(current_chunk+8,streamFile)) {
                        case 1:
                            if (!loop_start_found &&
                                (*loop_start = parse_marker(labelcontent))>=0)
                            {
                                loop_start_found = 1;
                            }
                            break;
                        case 2:
                            if (!loop_end_found &&
                                    (*loop_end = parse_marker(labelcontent))>=0)
                            {
                                loop_end_found = 1;
                            }
                            break;
                        default:
                            break;
                    }

                    free(labelcontent);
                }
                break;
            default:
                break;
        }

        current_chunk += 8 + chunk_size;
    }

    if (loop_start_found && loop_end_found) *loop_flag = 1;

    /* labels don't seem to be consistently ordered */
    if (*loop_start > *loop_end) {
        long temp = *loop_start;
        *loop_start = *loop_end;
        *loop_end = temp;
    }
}
Exemplo n.º 20
0
VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    STREAMFILE * streamFileMIH = NULL;
    char filename[260];
    
	uint8_t mibBuffer[0x10];
	uint8_t	testBuffer[0x10];
	uint8_t doChannelUpdate=1;
	uint8_t bDoUpdateInterleave=1;

	size_t	fileLength;
	
	off_t	loopStart = 0;
	off_t	loopEnd = 0;

	off_t	interleave = 0;

	off_t	readOffset = 0;

	char	filenameMIH[260];
	off_t	loopStartPoints[0x10];
	int		loopStartPointsCount=0;

	off_t	loopEndPoints[0x10];
	int		loopEndPointsCount=0;

	int		loopToEnd=0;
	int		forceNoLoop=0;
	int		gotEmptyLine=0;

	uint8_t gotMIH=0;

	int i, channel_count=0;

	// Initialize loop point to 0
	for(i=0; i<0x10; i++) {
		loopStartPoints[i]=0;
		loopEndPoints[i]=0;
	}

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("mib",filename_extension(filename)) && 
		strcasecmp("mi4",filename_extension(filename)) && 
		strcasecmp("vb",filename_extension(filename))  &&
		strcasecmp("xag",filename_extension(filename))) goto fail;

	/* check for .MIH file */
	strcpy(filenameMIH,filename);
	strcpy(filenameMIH+strlen(filenameMIH)-3,"MIH");

	streamFileMIH = streamFile->open(streamFile,filenameMIH,STREAMFILE_DEFAULT_BUFFER_SIZE);
	if (streamFileMIH) gotMIH = 1;

    /* Search for interleave value & loop points */
	/* Get the first 16 values */
	fileLength = get_streamfile_size(streamFile);
	
	readOffset+=(off_t)read_streamfile(mibBuffer,0,0x10,streamFile); 
	readOffset=0;
	mibBuffer[0]=0;

	do {
		readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 
		// be sure to point to an interleave value
		if(readOffset<(int32_t)(fileLength*0.5)) {

			if(memcmp(testBuffer+2, mibBuffer+2,0x0e)) {
				if(doChannelUpdate) {
					doChannelUpdate=0;
					channel_count++;
				}
				if(channel_count<2)
					bDoUpdateInterleave=1;
			}

			testBuffer[0]=0;
			if(!memcmp(testBuffer,mibBuffer,0x10)) {

				gotEmptyLine=1;

				if(bDoUpdateInterleave) {
					bDoUpdateInterleave=0;
					interleave=readOffset-0x10;
				}
				if(((readOffset-0x10)==(channel_count*interleave))) {
					doChannelUpdate=1;
				}
			}
		}

		// Loop Start ...
		if(testBuffer[0x01]==0x06) 
		{
			if(loopStartPointsCount<0x10) 
			{
				loopStartPoints[loopStartPointsCount] = readOffset-0x10;
				loopStartPointsCount++;
			}
		}

		// Loop End ...
		if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) {
			if(loopEndPointsCount<0x10) 
			{
				loopEndPoints[loopEndPointsCount] = readOffset;
				loopEndPointsCount++;
			}
		}

		if(testBuffer[0x01]==0x04) 
		{
			// 0x04 loop points flag can't be with a 0x03 loop points flag
			if(loopStartPointsCount<0x10) 
			{
				loopStartPoints[loopStartPointsCount] = readOffset-0x10;
				loopStartPointsCount++;

				// Loop end value is not set by flags ...
				// go until end of file
				loopToEnd=1;
			}
		}

	} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));

	if((testBuffer[0]==0x0c) && (testBuffer[1]==0))
		forceNoLoop=1;

	if(channel_count==0)
		channel_count=1;

	if(gotMIH) 
		channel_count=read_32bitLE(0x08,streamFileMIH);

	// force no loop
	if(!strcasecmp("vb",filename_extension(filename))) 
		loopStart=0;

	if(!strcasecmp("xag",filename_extension(filename))) 
		channel_count=2;

	// Calc Loop Points & Interleave ...
	if(loopStartPointsCount>=2) 
	{
		// can't get more then 0x10 loop point !
		if(loopStartPointsCount<=0x0F) {
			// Always took the first 2 loop points
			interleave=loopStartPoints[1]-loopStartPoints[0];
			loopStart=loopStartPoints[1];

			// Can't be one channel .mib with interleave values
			if((interleave>0) && (channel_count==1)) 
				channel_count=2;
		} else 
			loopStart=0;
	}

	if(loopEndPointsCount>=2) 
	{
		// can't get more then 0x10 loop point !
		if(loopEndPointsCount<=0x0F) {
			// No need to recalculate interleave value ...
			loopEnd=loopEndPoints[loopEndPointsCount-1];

			// Can't be one channel .mib with interleave values
			if(channel_count==1) channel_count=2;
		} else {
			loopToEnd=0;
			loopEnd=0;
		}
	}

	if (loopToEnd) 
		loopEnd=fileLength;

	// force no loop 
	if(forceNoLoop) 
		loopEnd=0;

	if((interleave>0x10) && (channel_count==1))
		channel_count=2;

	if(interleave==0) interleave=0x10;

	// further check on channel_count ...
	if(gotEmptyLine) 
	{
		int newChannelCount = 0;

		readOffset=0;

		do 
		{
			newChannelCount++;
			read_streamfile(testBuffer,readOffset,0x10,streamFile); 
			readOffset+=interleave;
		} while(!memcmp(testBuffer,mibBuffer,16));

		newChannelCount--;

		if(newChannelCount>channel_count)
			channel_count=newChannelCount;
	}

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,(loopEnd!=0));
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
	vgmstream->coding_type = coding_PSX;
    vgmstream->layout_type = layout_interleave;

	if(gotMIH) {
		// Read stuff from the MIH file 
		vgmstream->channels = read_32bitLE(0x08,streamFileMIH);
		vgmstream->sample_rate = read_32bitLE(0x0C,streamFileMIH);
		vgmstream->interleave_block_size = read_32bitLE(0x10,streamFileMIH);
		vgmstream->num_samples=((read_32bitLE(0x10,streamFileMIH)*
								(read_32bitLE(0x14,streamFileMIH)-1)*2)+
								((read_32bitLE(0x04,streamFileMIH)>>8)*2))/16*28/2;
	} else {
Exemplo n.º 21
0
/* .KLBS (L@VE ONCE PS3 */
VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile) 
{
    VGMSTREAM * vgmstream = NULL;
    char filename[1024];
    
	size_t fileLength;
	off_t readOffset = 0;
	off_t start_offset;
	off_t loop_start_offset;
	off_t loop_end_offset;

	uint8_t	testBuffer[0x10];
	int loop_flag = 0;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("bnk",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x20,streamFile) != 0x6B6C4253)
        goto fail;

	// get file length
	fileLength = get_streamfile_size(streamFile);	

	// Find loop start
	start_offset = read_32bitBE(0x10,streamFile);
	readOffset = start_offset;

	do {
		readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); 
		
		// Loop Start ...
		if(testBuffer[0x01] == 0x06) 
		{
			loop_start_offset = readOffset - 0x10;	
			break;
		}

	} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));

	// start at last line of file and move up
	readOffset = (int32_t)fileLength - 0x10;
	
	// Find loop end
	do {
		readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); 
		
		// Loop End ...
		if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) 
		{
			loop_end_offset = readOffset +  0x20;
			break;
		}
	} while (readOffset > 0);

	// setup loops
	if (loop_start_offset > 0)
	{
		loop_flag = 1;
		
		// if we have a start loop, use EOF if end loop is not found
		if (loop_end_offset == 0)
		{
			loop_end_offset = (int32_t)fileLength - 0x10;
		}
	}
	else
	{
		loop_flag = 0;
	}

    channel_count = 2;
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */		
    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = read_32bitBE(0x90, streamFile);
    vgmstream->meta_type = meta_PS3_KLBS;

	vgmstream->channels = channel_count;
    vgmstream->sample_rate = 48000;
    vgmstream->coding_type = coding_PSX;
	vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28);
 
	if (loop_flag) 
	{
		vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
		vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
	}

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 22
0
/**
 * open file containing decryption keys and copy to buffer
 * tries combinations of keynames based on the original filename
 *
 * returns true if found and copied
 */
int read_key_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile) {
    char keyname[PATH_LIMIT];
    char filename[PATH_LIMIT];
    const char *path, *ext;
    STREAMFILE * streamFileKey = NULL;

    streamFile->get_name(streamFile,filename,sizeof(filename));

    if (strlen(filename)+4 > sizeof(keyname)) goto fail;

    /* try to open a keyfile using variations:
     *  "(name.ext)key" (per song), "(.ext)key" (per folder) */
    {
        ext = strrchr(filename,'.');
        if (ext!=NULL) ext = ext+1;

        path = strrchr(filename,DIR_SEPARATOR);
        if (path!=NULL) path = path+1;

        /* "(name.ext)key" */
        strcpy(keyname, filename);
        strcat(keyname, "key");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;

        /* "(name.ext)KEY" */
        /*
        strcpy(keyname+strlen(keyname)-3,"KEY");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;
        */


        /* "(.ext)key" */
        if (path) {
            strcpy(keyname, filename);
            keyname[path-filename] = '\0';
            strcat(keyname, ".");
        } else {
            strcpy(keyname, ".");
        }
        if (ext) strcat(keyname, ext);
        strcat(keyname, "key");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;

        /* "(.ext)KEY" */
        /*
        strcpy(keyname+strlen(keyname)-3,"KEY");
        streamFileKey = streamFile->open(streamFile,keyname,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (streamFileKey) goto found;
        */

        goto fail;
    }

found:
    if (get_streamfile_size(streamFileKey) != bufsize) goto fail;

    if (read_streamfile(buf, 0, bufsize, streamFileKey)!=bufsize) goto fail;

    close_streamfile(streamFileKey);

    return 1;

fail:
    if (streamFileKey) close_streamfile(streamFileKey);

    return 0;
}
Exemplo n.º 23
0
VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
	char filename[PATH_LIMIT];
	off_t start_offset;
	uint8_t	testBuffer[0x10];
	off_t	loopStart = 0;
	off_t	loopEnd = 0;
	off_t	readOffset = 0;
	size_t	fileLength;
	int loop_flag;
	int channel_count;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("ass",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x02000000) /* "0x02000000" */
        goto fail;

    loop_flag = 1;
    channel_count = 2;
    
	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    start_offset = 0x800;
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
    vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = (read_32bitLE(0x08,streamFile)*2)*28/16/channel_count;
	
	fileLength = get_streamfile_size(streamFile);
		
	do {
		
		readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 
		/* Loop Start */
		if(testBuffer[0x01]==0x06) {
			if(loopStart == 0) loopStart = readOffset-0x10;
			/* break; */
		}
		/* Loop End */
		if(testBuffer[0x01]==0x03) {
			if(loopEnd == 0) loopEnd = readOffset-0x10;
			/* break; */
		}
	} while (streamFile->get_offset(streamFile)<(int32_t)fileLength);
	
	if(loopStart == 0) {
		loop_flag = 0;
		vgmstream->num_samples = read_32bitLE(0x4,streamFile)*28/16/channel_count;
	} else {
		loop_flag = 1;
		vgmstream->loop_start_sample = (loopStart-start_offset)*28/16/channel_count;
        	vgmstream->loop_end_sample = (loopEnd-start_offset)*28/16/channel_count;
    	}

    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile);
    vgmstream->meta_type = meta_PS2_ASS;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 24
0
VGMSTREAM * init_vgmstream_ps2_vbk(STREAMFILE *streamFile) 
{
    VGMSTREAM * vgmstream = NULL;
	char filename[260];
	off_t start_offset;
	uint8_t	testBuffer[0x10];
	off_t	loopStart = 0;
	off_t	loopEnd = 0;
	off_t	readOffset = 0;
	size_t	fileLength;
	int loop_flag;
	int channel_count;

    //_TCHAR szBuffer[100];

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("vbk",filename_extension(filename))) goto fail;

    /* check header */
    if (read_32bitBE(0x00,streamFile) != 0x2E56424B) /* .VBK */
        goto fail;

    loop_flag = 1;
    channel_count = read_32bitLE(0x28,streamFile) + 1;

	//_stprintf(szBuffer, _T("%x"), channel_count);
	//MessageBox(NULL, szBuffer, _T("Foo"), MB_OK);

	/* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

	/* fill in the vital statistics */
    fileLength = get_streamfile_size(streamFile);
	start_offset = read_32bitLE(0x0C, streamFile);
	vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x20,streamFile);
    vgmstream->coding_type = coding_PSX;
	vgmstream->num_samples = (fileLength - start_offset)*28/16/channel_count;
		
	// get loop start
	do {
		
		readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 

		if(testBuffer[0x01]==0x06) 
		{
			loopStart = readOffset-0x10;
			break;
		}

	} while (streamFile->get_offset(streamFile)<(int32_t)fileLength);
	
	
	// get loop end
	readOffset = fileLength - 0x10;
	
	do {		
		readOffset-=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 

		/* Loop End */
		if(testBuffer[0x01]==0x03) 
		{
			loopEnd = readOffset-0x10;
			break;
		}
	} while (readOffset > 0);

	loop_flag = 1;
	vgmstream->loop_start_sample = (loopStart-start_offset)*28/16/channel_count;
    vgmstream->loop_end_sample = (loopEnd-start_offset)*28/16/channel_count;

    vgmstream->layout_type = layout_interleave;
    vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile);
    vgmstream->meta_type = meta_PS2_VBK;

    /* open the file for reading */
    {
        int i;
        STREAMFILE * file;
        file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
        if (!file) goto fail;
        
		for (i=0;i<channel_count;i++) 
		{
            vgmstream->ch[i].streamfile = file;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=start_offset+
                vgmstream->interleave_block_size*i;

        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[260];

    int loop_flag=0;
    int channel_count;
	off_t start_offset;

	uint8_t	testBuffer[0x10];
	off_t	readOffset = 0;
	off_t	loopEnd = 0;

	int i;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("ads",filename_extension(filename)) && 
        strcasecmp("ss2",filename_extension(filename))) goto fail;

    /* check SShd Header */
    if (read_32bitBE(0x00,streamFile) != 0x53536864)
        goto fail;

    /* check SSbd Header */
    if (read_32bitBE(0x20,streamFile) != 0x53536264)
        goto fail;

    /* check if file is not corrupt */
    if (get_streamfile_size(streamFile)<(size_t)(read_32bitLE(0x24,streamFile) + 0x28))
        goto fail;

    /* check loop */
    loop_flag = (read_32bitLE(0x1C,streamFile)!=0xFFFFFFFF);

    channel_count=read_32bitLE(0x10,streamFile);

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->channels = read_32bitLE(0x10,streamFile);
    vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);

    /* Check for Compression Scheme */
    vgmstream->coding_type = coding_PSX;
    vgmstream->num_samples = ((read_32bitLE(0x24,streamFile)-0x40)/16*28)/vgmstream->channels;

	/* SS2 container with RAW Interleaved PCM */
    if (read_32bitLE(0x08,streamFile)!=0x10) {
        vgmstream->coding_type=coding_PCM16LE;
        vgmstream->num_samples = read_32bitLE(0x24,streamFile)/2/vgmstream->channels;
    }

    vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);
    vgmstream->layout_type = layout_interleave;
    vgmstream->meta_type = meta_PS2_SShd;

    /* Get loop point values */
    if(vgmstream->loop_flag) {
		if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) 
		{
			// Search for Loop Value
			readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); 

			do {
				readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); 
	
				// Loop End ...
				if(testBuffer[0x01]==0x01) {
					if(loopEnd==0) loopEnd = readOffset-0x10;
					break;
				}

			} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));

			vgmstream->loop_start_sample = 0;
			vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
			vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
			vgmstream->loop_end_sample /=vgmstream->channels;

		} else {
			if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
				vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
				vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
			} else {
				vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
				vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
			}
		}
    }

    /* don't know why, but it does happen, in ps2 too :( */
    if (vgmstream->loop_end_sample > vgmstream->num_samples)
        vgmstream->loop_end_sample = vgmstream->num_samples;

	start_offset=0x28;

	// Hack for files with start_offset = 0x800
	if(get_streamfile_size(streamFile)-read_32bitLE(0x24,streamFile)>=0x800)
		start_offset=0x800;

	if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28)) {
		start_offset=0x800;
		for(i=0;i<0x1f6;i+=4) {
			if(read_32bitLE(0x28+(i*4),streamFile)!=0) {
				start_offset=0x28;
				break;
			}
		}
	} 

	/* expect pcm format allways start @ 0x800, don't know if it's true :P */
	/*if(vgmstream->coding_type == coding_PCM16LE)
		start_offset=0x800;*/

    /* open the file for reading by each channel */
    {
        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);

            if (!vgmstream->ch[i].streamfile) goto fail;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=
                (off_t)(start_offset+vgmstream->interleave_block_size*i);
        }
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 26
0
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
    
	VGMSTREAM * vgmstream = NULL;
    
	int32_t channel_count;
    int32_t interleave;
    int32_t sample_rate;
    int32_t loop_start;
    int32_t loop_end;
    int32_t start_offset;
    int32_t header_size;
	int32_t coef[2];
	int32_t dsp_interleave_type;
	
    char filename[260];
    int coding;
#ifdef VGM_USE_MPEG
    mpeg_codec_data *data = NULL;
#endif

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("genh",filename_extension(filename))) goto fail;

    /* check header magic */
    if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;

    /* check channel count (needed for ADP/DTK check) */
    channel_count = read_32bitLE(0x4,streamFile);
    if (channel_count < 1) goto fail;

    /* check format */
    /* 0 = PSX ADPCM */
    /* 1 = XBOX IMA ADPCM */
    /* 2 = NGC ADP/DTK ADPCM */
    /* 3 = 16bit big endian PCM */
    /* 4 = 16bit little endian PCM */
    /* 5 = 8bit PCM */
    /* 6 = SDX2 */
    /* 7 = DVI IMA */
    /* 8 = MPEG-1 Layer III, possibly also the MPEG-2 and 2.5 extensions */
    /* 9 = IMA */
    /* 10 = AICA ADPCM */
    /* 11 = MS ADPCM */
    /* 12 = NGC DSP */
    /* 13 = 8bit unsingned PCM */
	/* 14 = PSX ADPCM (bad flagged) */
    /* ... others to come */
    switch (read_32bitLE(0x18,streamFile)) {
        case 0:
            coding = coding_PSX;
            break;
        case 1:
            coding = coding_XBOX;
            break;
        case 2:
            coding = coding_NGC_DTK;
            if (channel_count != 2) goto fail;
            break;
        case 3:
            coding = coding_PCM16BE;
            break;
        case 4:
            coding = coding_PCM16LE;
            break;
        case 5:
            coding = coding_PCM8;
            break;
        case 6:
            coding = coding_SDX2;
            break;
        case 7:
            coding = coding_DVI_IMA;
            break;
#ifdef VGM_USE_MPEG
        case 8:
            /* we say MPEG-1 L3 here, but later find out exactly which */
            coding = coding_MPEG1_L3;
            break;
#endif
        case 9:
            coding = coding_IMA;
            break;
        case 10:
            coding = coding_AICA;
            break;
        case 11:
            coding = coding_MSADPCM;
            break;
        case 12:
            coding = coding_NGC_DSP;
            break;
		case 13:
            coding = coding_PCM8_U_int;
            break;
		case 14:
            coding = coding_PSX_badflags;
            break;
        default:
            goto fail;
    }

    start_offset = read_32bitLE(0x1C,streamFile);
    header_size = read_32bitLE(0x20,streamFile);

    /* HACK to support old genh */
    if (header_size == 0) {
        start_offset = 0x800;
        header_size = 0x800;
    }

    /* check for audio data start past header end */
    if (header_size > start_offset) goto fail;

    interleave = read_32bitLE(0x8,streamFile);
    sample_rate = read_32bitLE(0xc,streamFile);
    loop_start = read_32bitLE(0x10,streamFile);
    loop_end = read_32bitLE(0x14,streamFile);
	
	coef[0] = read_32bitLE(0x24,streamFile);
	coef[1] = read_32bitLE(0x28,streamFile);
	dsp_interleave_type = read_32bitLE(0x2C,streamFile);

    //if (coding == coding_XBOX && channel_count != 2) goto fail;

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,(loop_start!=-1));
    if (!vgmstream) goto fail;

    /* fill in the vital information */

    vgmstream->channels = channel_count;
    vgmstream->sample_rate = sample_rate;
    vgmstream->num_samples = loop_end;
    vgmstream->loop_start_sample = loop_start;
    vgmstream->loop_end_sample = loop_end;
    vgmstream->loop_flag = (loop_start != -1);

    switch (coding) {
        case coding_PCM8_U_int:
			vgmstream->layout_type=layout_none;
			break;
		case coding_PCM16LE:
        case coding_PCM16BE:
        case coding_PCM8:
        case coding_SDX2:
        case coding_PSX:
		case coding_PSX_badflags:
        case coding_DVI_IMA:
        case coding_IMA:
        case coding_AICA:
            vgmstream->interleave_block_size = interleave;
            if (channel_count > 1)
            {
                if (coding == coding_SDX2) {
                    coding = coding_SDX2_int;
                    vgmstream->coding_type = coding_SDX2_int;
                }
				if(vgmstream->interleave_block_size==0xffffffff)
					vgmstream->layout_type=layout_none;
				else {
					vgmstream->layout_type = layout_interleave;
					if(coding==coding_DVI_IMA)
						coding=coding_INT_DVI_IMA;
					if(coding==coding_IMA)
						coding=coding_INT_IMA;
				}
            } else {
                vgmstream->layout_type = layout_none;
            }
            break;
        case coding_MSADPCM:
            if (channel_count != 2) goto fail;
            vgmstream->interleave_block_size = interleave;
            vgmstream->layout_type = layout_none;
            break;
        case coding_XBOX:
            vgmstream->layout_type = layout_none;
            break;
        case coding_NGC_DTK:
            vgmstream->layout_type = layout_dtk_interleave;
            break;
        case coding_NGC_DSP:
        	if (dsp_interleave_type == 0) {
				vgmstream->layout_type = layout_interleave;
            	vgmstream->interleave_block_size = interleave;
			} else if (dsp_interleave_type == 1) {
        		vgmstream->layout_type = layout_interleave_byte;
            	vgmstream->interleave_block_size = interleave;
			} else if (dsp_interleave_type == 2) {
            	vgmstream->layout_type = layout_none;
			}
			break;
            
#ifdef VGM_USE_MPEG
        case coding_MPEG1_L3:
            vgmstream->layout_type = layout_mpeg;
            break;
#endif
    }
    
	vgmstream->coding_type = coding;
	vgmstream->meta_type = meta_GENH;
    
    /* open the file for reading by each channel */
    {
        int i;
		int j;

        STREAMFILE * chstreamfile = NULL;

        for (i=0;i<channel_count;i++) {
            off_t chstart_offset = start_offset;

            switch (coding) {
                case coding_PSX:
				case coding_PSX_badflags:
                case coding_PCM16BE:
                case coding_PCM16LE:
                case coding_SDX2:
                case coding_SDX2_int:
                case coding_DVI_IMA:
                case coding_IMA:
                case coding_PCM8:
                case coding_PCM8_U_int:
                case coding_AICA:
				case coding_INT_DVI_IMA:
				case coding_INT_IMA:
                    if (vgmstream->layout_type == layout_interleave) {
                        if (interleave >= 512) {
                            chstreamfile =
                                streamFile->open(streamFile,filename,interleave);
                        } else {
                            if (!chstreamfile)
                                chstreamfile =
                                    streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
                        }
                        chstart_offset =
                            start_offset+vgmstream->interleave_block_size*i;
                    } else {
                        chstreamfile =
                            streamFile->open(streamFile,filename,
                                    STREAMFILE_DEFAULT_BUFFER_SIZE);
                    }
                    break;
                case coding_XBOX:
                case coding_MSADPCM:
                    /* xbox's "interleave" is a lie, all channels start at same
                     * offset */
                    chstreamfile =
                        streamFile->open(streamFile,filename,
                                STREAMFILE_DEFAULT_BUFFER_SIZE);
                    break;
                case coding_NGC_DTK:
                    if (!chstreamfile) 
                        chstreamfile =
                            streamFile->open(streamFile,filename,32*0x400);
                    break;
                case coding_NGC_DSP:
                    if (!chstreamfile) 
                        chstreamfile =
                            streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);

					for (j=0;j<16;j++) 
            			vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef[i]+j*2,streamFile);
							chstart_offset =start_offset+vgmstream->interleave_block_size*i;
					break;

#ifdef VGM_USE_MPEG
                case coding_MPEG1_L3:
                    if (!chstreamfile)
                        chstreamfile =
                            streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE);
                    break;
#endif
            }

            if (!chstreamfile) goto fail;

            vgmstream->ch[i].streamfile = chstreamfile;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=chstart_offset;
        }
    }

#ifdef VGM_USE_MPEG
    if (coding == coding_MPEG1_L3) {
        int rc;
        off_t read_offset;
        data = calloc(1,sizeof(mpeg_codec_data));
        if (!data) goto mpeg_fail;

        data->m = mpg123_new(NULL,&rc);
        if (rc==MPG123_NOT_INITIALIZED) {
            if (mpg123_init()!=MPG123_OK) goto mpeg_fail;
            data->m = mpg123_new(NULL,&rc);
            if (rc!=MPG123_OK) goto mpeg_fail;
        } else if (rc!=MPG123_OK) {
            goto mpeg_fail;
        }

        mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0);

        if (mpg123_open_feed(data->m)!=MPG123_OK) {
            goto mpeg_fail;
        }

        /* check format */
        read_offset=0;
        do {
            size_t bytes_done;
            if (read_streamfile(data->buffer, start_offset+read_offset,
                    MPEG_BUFFER_SIZE,vgmstream->ch[0].streamfile) !=
                    MPEG_BUFFER_SIZE) goto mpeg_fail;
            read_offset+=1;
            rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE,
                    NULL,0,&bytes_done);
            if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT &&
                    rc != MPG123_NEED_MORE) goto mpeg_fail;
        } while (rc != MPG123_NEW_FORMAT);

        {
            long rate;
            int channels,encoding;
            struct mpg123_frameinfo mi;
            rc = mpg123_getformat(data->m,&rate,&channels,&encoding);
            if (rc != MPG123_OK) goto mpeg_fail;
            if (rate != vgmstream->sample_rate ||
                    channels != vgmstream->channels ||
                    encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail;
            mpg123_info(data->m,&mi);
            if (mi.rate != vgmstream->sample_rate) goto mpeg_fail;
            if (mi.version == MPG123_1_0 && mi.layer == 1)
                vgmstream->coding_type = coding_MPEG1_L1;
            else if (mi.version == MPG123_1_0 && mi.layer == 2)
                vgmstream->coding_type = coding_MPEG1_L2;
            else if (mi.version == MPG123_1_0 && mi.layer == 3)
                vgmstream->coding_type = coding_MPEG1_L3;
            else if (mi.version == MPG123_2_0 && mi.layer == 1)
                vgmstream->coding_type = coding_MPEG2_L1;
            else if (mi.version == MPG123_2_0 && mi.layer == 2)
                vgmstream->coding_type = coding_MPEG2_L2;
            else if (mi.version == MPG123_2_0 && mi.layer == 3)
                vgmstream->coding_type = coding_MPEG2_L3;
            else if (mi.version == MPG123_2_5 && mi.layer == 1)
                vgmstream->coding_type = coding_MPEG25_L1;
            else if (mi.version == MPG123_2_5 && mi.layer == 2)
                vgmstream->coding_type = coding_MPEG25_L2;
            else if (mi.version == MPG123_2_5 && mi.layer == 3)
                vgmstream->coding_type = coding_MPEG25_L3;
            else goto mpeg_fail;
        }

        /* reinit, to ignore the reading we've done so far */
        mpg123_open_feed(data->m);

        vgmstream->codec_data = data;
    }
#endif

    return vgmstream;

    /* clean up anything we may have opened */
#ifdef VGM_USE_MPEG
mpeg_fail:
    if (data) {
        mpg123_delete(data->m);
        free(data);
    }
#endif
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    return NULL;
}
Exemplo n.º 27
0
/* @UTF table reading, abridged */
static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query)
{
    unsigned char buf[4];
    struct utf_table_info table_info;
    char *string_table = NULL;
    struct utf_column_info * schema = NULL;
    struct utf_query_result result;
    uint32_t table_name_string;
    int string_table_size;
    
    result.valid = 0;

    table_info.table_offset = offset;

    /* check header */
    {
        static const char UTF_signature[4] = "@UTF"; /* intentionally unterminated */
        if (4 != read_streamfile(buf, offset, 4, infile)) goto cleanup_error;
        if (memcmp(buf, UTF_signature, sizeof(UTF_signature)))
        {
            goto cleanup_error;
        }
    }

    /* get table size */
    table_info.table_size = read_32bitBE(offset+4, infile);

    table_info.schema_offset = 0x20;
    table_info.rows_offset = read_32bitBE(offset+8, infile);
    table_info.string_table_offset = read_32bitBE(offset+0xc,infile);
    table_info.data_offset = read_32bitBE(offset+0x10,infile);
    table_name_string = read_32bitBE(offset+0x14,infile);
    table_info.columns = read_16bitBE(offset+0x18,infile);
    table_info.row_width = read_16bitBE(offset+0x1a,infile);
    table_info.rows = read_32bitBE(offset+0x1c,infile);

    /* allocate for string table */
    string_table_size = table_info.data_offset-table_info.string_table_offset;
    string_table = malloc(string_table_size+1);
    if (!string_table) goto cleanup_error;
    table_info.string_table = string_table;
    memset(string_table, 0, string_table_size+1);

    /* load schema */
    schema = malloc(sizeof(struct utf_column_info) * table_info.columns);
    if (!schema) goto cleanup_error;

    {
        int i;
        long schema_current_offset = table_info.schema_offset;
        for (i = 0; i < table_info.columns; i++)
        {
            schema[i].type = read_8bit(schema_current_offset,infile);
            schema_current_offset ++;
            schema[i].column_name = string_table + read_32bitBE(schema_current_offset,infile);
            schema_current_offset += 4;

            if ((schema[i].type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT)
            {
                schema[i].constant_offset = schema_current_offset;
                switch (schema[i].type & COLUMN_TYPE_MASK)
                {
                    case COLUMN_TYPE_8BYTE:
                    case COLUMN_TYPE_DATA:
                        schema_current_offset+=8;
                        break;
                    case COLUMN_TYPE_STRING:
                    case COLUMN_TYPE_FLOAT:
                    case COLUMN_TYPE_4BYTE:
                        schema_current_offset+=4;
                        break;
                    case COLUMN_TYPE_2BYTE2:
                    case COLUMN_TYPE_2BYTE:
                        schema_current_offset+=2;
                        break;
                    case COLUMN_TYPE_1BYTE2:
                    case COLUMN_TYPE_1BYTE:
                        schema_current_offset++;
                        break;
                    default:
                        goto cleanup_error;
                }
            }
        }
    }

    table_info.schema = schema;

    /* read string table */
    read_streamfile((unsigned char *)string_table,
            table_info.string_table_offset+8+offset,
            string_table_size, infile);
    table_info.table_name = table_info.string_table+table_name_string;

    /* fill in the default stuff */
    result.found = 0;
    result.rows = table_info.rows;
    result.name_offset = table_name_string;
    result.string_table_offset = table_info.string_table_offset;
    result.data_offset = table_info.data_offset;

    /* explore the values */
    if (query) {
        int i, j;

        for (i = 0; i < table_info.rows; i++)
        {
            uint32_t row_offset =
                table_info.table_offset + 8 + table_info.rows_offset +
                i * table_info.row_width;
            const uint32_t row_start_offset = row_offset;

            if (query && i != query->index) continue;

            for (j = 0; j < table_info.columns; j++)
            {
                uint8_t type = table_info.schema[j].type;
                long constant_offset = table_info.schema[j].constant_offset;
                int constant = 0;

                int qthis = (query && i == query->index &&
                        !strcmp(table_info.schema[j].column_name, query->name));

                if (qthis)
                {
                    result.found = 1;
                    result.type = schema[j].type & COLUMN_TYPE_MASK;
                }

                switch (schema[j].type & COLUMN_STORAGE_MASK)
                {
                    case COLUMN_STORAGE_PERROW:
                        break;
                    case COLUMN_STORAGE_CONSTANT:
                        constant = 1;
                        break;
                    case COLUMN_STORAGE_ZERO:
                        if (qthis)
                        {
                            memset(&result.value, 0,
                                    sizeof(result.value));
                        }
                        continue;
                    default:
                        goto cleanup_error;
                }

                if (1)
                {
                    long data_offset;
                    int bytes_read;

                    if (constant)
                    {
                        data_offset = constant_offset;
                    }
                    else
                    {
                        data_offset = row_offset;
                    }

                    switch (type & COLUMN_TYPE_MASK)
                    {
                        case COLUMN_TYPE_STRING:
                            {
                                uint32_t string_offset;
                                string_offset = read_32bitBE(data_offset, infile);
                                bytes_read = 4;
                                if (qthis)
                                {
                                    result.value.value_string = string_offset;
                                }
                            }
                            break;
                        case COLUMN_TYPE_DATA:
                            {
                                uint32_t vardata_offset, vardata_size;

                                vardata_offset = read_32bitBE(data_offset, infile);
                                vardata_size = read_32bitBE(data_offset+4, infile);
                                bytes_read = 8;
                                if (qthis)
                                {
                                    result.value.value_data.offset = vardata_offset;
                                    result.value.value_data.size = vardata_size;
                                }
                            }
                            break;

                        case COLUMN_TYPE_8BYTE:
                            {
                                uint64_t value =
                                    read_32bitBE(data_offset, infile);
                                value <<= 32;
                                value |=
                                    read_32bitBE(data_offset+4, infile);
                                if (qthis)
                                {
                                    result.value.value_u64 = value;
                                }
                                bytes_read = 8;
                                break;
                            }
                        case COLUMN_TYPE_4BYTE:
                            {
                                uint32_t value =
                                    read_32bitBE(data_offset, infile);
                                if (qthis)
                                {
                                    result.value.value_u32 = value;
                                }
                                bytes_read = 4;
                            }
                            break;
                        case COLUMN_TYPE_2BYTE2:
                        case COLUMN_TYPE_2BYTE:
                            {
                                uint16_t value = 
                                    read_16bitBE(data_offset, infile);
                                if (qthis)
                                {
                                    result.value.value_u16 = value;
                                }
                                bytes_read = 2;
                            }
                            break;
                        case COLUMN_TYPE_FLOAT:
                            if (sizeof(float) == 4)
                            {
                                union {
                                    float float_value;
                                    uint32_t int_value;
                                } int_float;

                                int_float.int_value = read_32bitBE(data_offset, infile);
                                if (qthis)
                                {
                                    result.value.value_float = int_float.float_value;
                                }
                            }
                            else
                            {
                                read_32bitBE(data_offset, infile);
                                if (qthis)
                                {
                                    goto cleanup_error;
                                }
                            }
                            bytes_read = 4;
                            break;
                        case COLUMN_TYPE_1BYTE2:
                        case COLUMN_TYPE_1BYTE:
                            {
                                uint8_t value =
                                    read_8bit(data_offset, infile);
                                if (qthis)
                                {
                                    result.value.value_u8 = value;
                                }
                                bytes_read = 1;
                            }
                            break;
                        default:
                            goto cleanup_error;
                    }

                    if (!constant)
                    {
                        row_offset += bytes_read;
                    }
                } /* useless if end */
            } /* column for loop end */

            if (row_offset - row_start_offset != table_info.row_width)
                goto cleanup_error;

            if (query && i >= query->index) break;
        } /* row for loop end */
    } /* explore values block end */

//cleanup:

    result.valid = 1;
cleanup_error:

    if (string_table)
    {
        free(string_table);
        string_table = NULL;
    }

    if (schema)
    {
        free(schema);
        schema = NULL;
    }

    return result;
}
Exemplo n.º 28
0
VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
    VGMSTREAM * vgmstream = NULL;
    char filename[PATH_LIMIT];
	int i;
    int channel_count;
    int loop_flag = 0;
    int32_t loop_start_sample = 0;
    int32_t loop_end_sample = 0;
    int nwainfo_ini_found = 0;
    int gameexe_ini_found = 0;
    int just_pcm = 0;
    int comp_level = -2;
    nwa_codec_data *data = NULL;

    /* check extension, case insensitive */
    streamFile->get_name(streamFile,filename,sizeof(filename));
    if (strcasecmp("nwa",filename_extension(filename))) goto fail;

    channel_count = read_16bitLE(0x00,streamFile);
    if (channel_count != 1 && channel_count != 2) goto fail;

    /* check if we're using raw pcm */
    if (
            read_32bitLE(0x08,streamFile)==-1 || /* compression level */
            read_32bitLE(0x10,streamFile)==0  || /* block count */
            read_32bitLE(0x18,streamFile)==0  || /* compressed data size */
            read_32bitLE(0x20,streamFile)==0  || /* block size */
            read_32bitLE(0x24,streamFile)==0     /* restsize */
       )
    {
        just_pcm = 1;
    }
    else
    {
        comp_level = read_32bitLE(0x08,streamFile);

        data = malloc(sizeof(nwa_codec_data));
        if (!data) goto fail;

        data->nwa = open_nwa(streamFile,filename);
        if (!data->nwa) goto fail;
    }

    /* try to locate NWAINFO.INI in the same directory */
    {
        char ininame[PATH_LIMIT];
        char * ini_lastslash;
        char namebase_array[PATH_LIMIT];
        char *namebase;
        STREAMFILE *inistreamfile;

        /* here we assume that the "special encoding" does not affect
         * the directory separator */
        strncpy(ininame,filename,sizeof(ininame));
        ininame[sizeof(ininame)-1]='\0';    /* a pox on the stdlib! */

        streamFile->get_realname(streamFile,namebase_array,sizeof(namebase_array));

        ini_lastslash = strrchr(ininame,DIRSEP);
        if (!ini_lastslash) {
            strncpy(ininame,"NWAINFO.INI",sizeof(ininame));
            namebase = namebase_array;
        } else {
            strncpy(ini_lastslash+1,"NWAINFO.INI",
                    sizeof(ininame)-(ini_lastslash+1-ininame));
            namebase = strrchr(namebase_array,DIRSEP)+1;
        }
        ininame[sizeof(ininame)-1]='\0';    /* curse you, strncpy! */

        inistreamfile = streamFile->open(streamFile,ininame,4096);

        if (inistreamfile) {
            /* ini found, try to find our name */
            const char * ext;
            int length;
            int found;
            off_t offset;
            off_t file_size;
            off_t found_off = -1;

            nwainfo_ini_found = 1;

            ext = filename_extension(namebase);
            length = ext-1-namebase;
            file_size = get_streamfile_size(inistreamfile);

            for (found = 0, offset = 0; !found && offset<file_size; offset++) {
                off_t suboffset;
                /* Go for an n*m search 'cause it's easier than building an
                 * FSA for the search string. Just wanted to make the point that
                 * I'm not ignorant, just lazy. */
                for (suboffset = offset;
                        suboffset<file_size &&
                        suboffset-offset<length &&
                        read_8bit(suboffset,inistreamfile)==
                            namebase[suboffset-offset];
                        suboffset++) {}

                if (suboffset-offset==length &&
                        read_8bit(suboffset,inistreamfile)==0x09) { /* tab */
                    found=1;
                    found_off = suboffset+1;
                }
            }

            if (found) {
                char loopstring[9]={0};

                if (read_streamfile((uint8_t*)loopstring,found_off,8,
                            inistreamfile)==8)
                {
                    loop_start_sample = atol(loopstring);
                    if (loop_start_sample > 0) loop_flag = 1;
                }
            }   /* if found file name in INI */

            close_streamfile(inistreamfile);
        } /* if opened INI ok */
    } /* INI block */

    /* try to locate Gameexe.ini in the same directory */
    {
        char ininame[PATH_LIMIT];
        char * ini_lastslash;
        char namebase_array[PATH_LIMIT];
        char * namebase;
        STREAMFILE *inistreamfile;

        strncpy(ininame,filename,sizeof(ininame));
        ininame[sizeof(ininame)-1]='\0';    /* a pox on the stdlib! */

        streamFile->get_realname(streamFile,namebase_array,sizeof(namebase_array));

        ini_lastslash = strrchr(ininame,DIRSEP);
        if (!ini_lastslash) {
            strncpy(ininame,"Gameexe.ini",sizeof(ininame));
            namebase = namebase_array;
        } else {
            strncpy(ini_lastslash+1,"Gameexe.ini",
                    sizeof(ininame)-(ini_lastslash+1-ininame));
            namebase = strrchr(namebase_array,DIRSEP)+1;
        }
        ininame[sizeof(ininame)-1]='\0';    /* curse you, strncpy! */

        inistreamfile = streamFile->open(streamFile,ininame,4096);

        if (inistreamfile) {
            /* ini found, try to find our name */
            const char * ext;
            int length;
            int found;
            off_t offset;
            off_t file_size;
            off_t found_off = -1;

            gameexe_ini_found = 1;

            ext = filename_extension(namebase);
            length = ext-1-namebase;
            file_size = get_streamfile_size(inistreamfile);

            /* format of line is:
             * #DSTRACK = 00000000 - eeeeeeee - ssssssss = "name"    = "name2?"
             *                       ^22        ^33         ^45         ^57
             */

            for (found = 0, offset = 0; !found && offset<file_size; offset++) {
                off_t suboffset;
                uint8_t buf[10];

                if (read_8bit(offset,inistreamfile)!='#') continue;
                if (read_streamfile(buf,offset+1,10,inistreamfile)!=10) break;
                if (memcmp("DSTRACK = ",buf,10)) continue;
                if (read_8bit(offset+44,inistreamfile)!='\"') continue;

                for (suboffset = offset+45;
                        suboffset<file_size &&
                        suboffset-offset-45<length &&
                        tolower(read_8bit(suboffset,inistreamfile))==
                            tolower(namebase[suboffset-offset-45]);
                        suboffset++) {}

                if (suboffset-offset-45==length &&
                        read_8bit(suboffset,inistreamfile)=='\"') { /* tab */
                    found=1;
                    found_off = offset+22; /* loop end */
                }
            }

            if (found) {
                char loopstring[9]={0};
                int start_ok = 0, end_ok = 0;
                int32_t total_samples =
                    read_32bitLE(0x1c,streamFile)/channel_count;

                if (read_streamfile((uint8_t*)loopstring,found_off,8,
                            inistreamfile)==8)
                {
                    if (!memcmp("99999999",loopstring,8))
                    {
                        loop_end_sample = total_samples;
                    }
                    else
                    {
                        loop_end_sample = atol(loopstring);
                    }
                    end_ok = 1;
                }
                if (read_streamfile((uint8_t*)loopstring,found_off+11,8,
                            inistreamfile)==8)
                {
                    if (!memcmp("99999999",loopstring,8))
                    {
                        /* not ok to start at last sample,
                         * don't set start_ok flag */
                    }
                    else if (!memcmp("00000000",loopstring,8))
                    {
                        /* loops from the start aren't really loops */
                    }
                    else
                    {
                        loop_start_sample = atol(loopstring);
                        start_ok = 1;
                    }
                }

                if (start_ok && end_ok) loop_flag = 1;
            }   /* if found file name in INI */

            close_streamfile(inistreamfile);
        } /* if opened INI ok */
    } /* INI block */

    /* build the VGMSTREAM */
    vgmstream = allocate_vgmstream(channel_count,loop_flag);
    if (!vgmstream) goto fail;

    /* fill in the vital statistics */
    vgmstream->channels = channel_count;
    vgmstream->sample_rate = read_32bitLE(0x04,streamFile);

    vgmstream->num_samples = read_32bitLE(0x1c,streamFile)/channel_count;

    if (just_pcm) {
        switch (read_16bitLE(0x02,streamFile)) {
            case 8:
                vgmstream->coding_type = coding_PCM8;
                vgmstream->interleave_block_size = 1;
                break;
            case 16:
                vgmstream->coding_type = coding_PCM16LE;
                vgmstream->interleave_block_size = 2;
                break;
            default:
                goto fail;
        }
        if (channel_count > 1) {
            vgmstream->layout_type = layout_interleave;
        } else {
            vgmstream->layout_type = layout_none;
        }
    }
    else
    {
        switch (comp_level)
        {
            case 0:
                vgmstream->coding_type = coding_NWA0;
                break;
            case 1:
                vgmstream->coding_type = coding_NWA1;
                break;
            case 2:
                vgmstream->coding_type = coding_NWA2;
                break;
            case 3:
                vgmstream->coding_type = coding_NWA3;
                break;
            case 4:
                vgmstream->coding_type = coding_NWA4;
                break;
            case 5:
                vgmstream->coding_type = coding_NWA5;
                break;
            default:
                goto fail;
                break;
        }
        vgmstream->layout_type = layout_none;
    }

    if (nwainfo_ini_found) {
        vgmstream->meta_type = meta_NWA_NWAINFOINI;
        if (loop_flag) {
            vgmstream->loop_start_sample = loop_start_sample;
            vgmstream->loop_end_sample = vgmstream->num_samples;
        }
    } else if (gameexe_ini_found) {
        vgmstream->meta_type = meta_NWA_GAMEEXEINI;
        if (loop_flag) {
            vgmstream->loop_start_sample = loop_start_sample;
            vgmstream->loop_end_sample = loop_end_sample;
        }
    } else {
        vgmstream->meta_type = meta_NWA;
    }


    if (just_pcm) {
        /* open the file for reading by each channel */
        STREAMFILE *chstreamfile;

        /* have both channels use the same buffer, as interleave is so small */
        chstreamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);

        if (!chstreamfile) goto fail;

        for (i=0;i<channel_count;i++) {
            vgmstream->ch[i].streamfile = chstreamfile;

            vgmstream->ch[i].channel_start_offset=
                vgmstream->ch[i].offset=0x2c+(off_t)(i*vgmstream->interleave_block_size);
        }
    }
    else
    {
        vgmstream->codec_data = data;
    }

    return vgmstream;

    /* clean up anything we may have opened */
fail:
    if (vgmstream) close_vgmstream(vgmstream);
    if (data) {
        if (data->nwa)
        {
            close_nwa(data->nwa);
        }
        free(data);
    }
    return NULL;
}