/* set up for the block at the given offset */ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) { int i,j; STREAMFILE *streamFile=vgmstream->ch[0].streamfile; off_t start_offset; int32_t nextFrameSize; vgmstream->current_block_offset = block_offset; nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile); vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->full_block_size; vgmstream->full_block_size = nextFrameSize; start_offset=vgmstream->current_block_offset + read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10; vgmstream->current_block_size=read_32bitBE(start_offset,streamFile); start_offset+=8; for(i=0;i<vgmstream->channels;i++) { for(j=0;j<16;j++) { vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(start_offset+(i*0x20)+(j*2),streamFile); } vgmstream->ch[i].adpcm_history1_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4),streamFile); vgmstream->ch[i].adpcm_history2_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4) + 2,streamFile); vgmstream->ch[i].offset = start_offset + (0x24*vgmstream->channels)+(i*vgmstream->current_block_size); } }
/* VGV (from Rune: Viking Warlord) */ VGMSTREAM * init_vgmstream_ps2_vgv(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; off_t start_offset; int loop_flag = 0; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("vgv",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x08,streamFile) != 0x0) goto fail; if (read_32bitBE(0x0C,streamFile) != 0x0) goto fail; loop_flag = 0; channel_count = 1; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x10; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = (get_streamfile_size(streamFile))*28/16/channel_count; if (loop_flag) { vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; } vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_PS2_VGV; /* 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; }
/* RSD6RADP */ VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; off_t start_offset; int loop_flag; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("rsd",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ goto fail; if (read_32bitBE(0x4,streamFile) != 0x52414450) /* RADP */ goto fail; loop_flag = 0; channel_count = read_32bitLE(0x8,streamFile); /* 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(0x10,streamFile); vgmstream->coding_type = coding_RAD_IMA; vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/0x14/channel_count*32; if (loop_flag) { vgmstream->loop_start_sample = loop_flag; vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; } vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = 0x14*channel_count; vgmstream->meta_type = meta_RSD6RADP; /* 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].offset=vgmstream->ch[i].channel_start_offset=start_offset; } } return vgmstream; fail: /* clean up anything we may have opened */ if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* GCM (from NamCollection) */ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; off_t start_offset; int loop_flag; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("gcm",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x4D434700) /* "MCG" */ goto fail; if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */ goto fail; 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 */ start_offset = 0x80; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x30,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x10,streamFile)*28/32; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); vgmstream->meta_type = meta_PS2_GCM; /* 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_xbox_xmu(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; int loop_flag=0; int channel_count; int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("xmu",filename_extension(filename))) goto fail; if((read_32bitBE(0x00,streamFile)!=0x584D5520) && (read_32bitBE(0x08,streamFile)!=0x46524D54)) goto fail; /* No Loop found atm */ loop_flag = read_8bit(0x16,streamFile);; /* Always stereo files */ channel_count=read_8bit(0x14,streamFile); /* 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(0x10,streamFile); vgmstream->coding_type = coding_XBOX; vgmstream->num_samples = read_32bitLE(0x7FC,streamFile) / 36 * 64 / vgmstream->channels; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_XBOX_XMU; if(loop_flag) { vgmstream->loop_start_sample=0; vgmstream->loop_end_sample=vgmstream->num_samples; } /* open the file for reading by each channel */ { for (i=0;i<channel_count;i++) { vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36); vgmstream->ch[i].offset = 0x800; if (!vgmstream->ch[i].streamfile) goto fail; } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; int channel_count; int loop_flag = 0; off_t start_offset; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("myspd",filename_extension(filename))) goto fail; channel_count = 2; start_offset = 0x20; /* check size */ if ((read_32bitBE(0x0,streamFile)*channel_count+start_offset) != get_streamfile_size(streamFile)) goto fail; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ vgmstream->num_samples = read_32bitBE(0x0,streamFile) * 2; vgmstream->sample_rate = read_32bitBE(0x4,streamFile); vgmstream->coding_type = coding_IMA; vgmstream->meta_type = meta_MYSPD; vgmstream->layout_type = layout_none; /* open the file for reading */ { STREAMFILE * file; file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!file) goto fail; vgmstream->ch[0].streamfile = file; vgmstream->ch[0].channel_start_offset= vgmstream->ch[0].offset=start_offset; file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!file) goto fail; vgmstream->ch[1].streamfile = file; vgmstream->ch[0].channel_start_offset= vgmstream->ch[1].offset=start_offset + read_32bitBE(0x0,streamFile); } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
static void read_rwar(struct rwav_data * rd) { if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574152) /* "RWAR" */ return; if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0100) /* version 0 */ return; rd->offset += 0x60; read_rwav(rd); rd->version = 0; return; }
VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; size_t file_size; off_t start_offset; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("lsf",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x0, streamFile) != 0x216E316E || // "!n1n" read_32bitBE(0x4, streamFile) != 0x6A346E00) // "j4n\0" goto fail; /* check size */ file_size = get_streamfile_size(streamFile); if (read_32bitLE(0xC, streamFile) + 0x10 != file_size) goto fail; start_offset = 0x10; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(1,0); if (!vgmstream) goto fail; /* fill in the vital statistics */ vgmstream->num_samples = (file_size-0x10)/0x1c*0x1b*2; vgmstream->sample_rate = read_32bitLE(0x8, streamFile); vgmstream->coding_type = coding_LSF; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_LSF_N1NJ4N; /* open the file for reading */ { vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!vgmstream->ch[0].streamfile) goto fail; vgmstream->ch[0].channel_start_offset= vgmstream->ch[0].offset=start_offset; } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) { int i; off_t block_size=vgmstream->current_block_size; if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) { block_offset+=0x0C; } vgmstream->current_block_offset = block_offset; if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E64) { /* 1Snd */ block_offset+=4; if(vgmstream->ea_platform==0) block_size=read_32bitLE(vgmstream->current_block_offset+0x04, vgmstream->ch[0].streamfile); else block_size=read_32bitBE(vgmstream->current_block_offset+0x04, vgmstream->ch[0].streamfile); block_offset+=4; } vgmstream->current_block_size=block_size-8; if(vgmstream->coding_type==coding_EACS_IMA) { init_get_high_nibble(vgmstream); vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile); for(i=0;i<vgmstream->channels;i++) { vgmstream->ch[i].adpcm_step_index = read_32bitLE(block_offset+0x04+i*4,vgmstream->ch[0].streamfile); vgmstream->ch[i].adpcm_history1_32 = read_32bitLE(block_offset+0x04+i*4+(4*vgmstream->channels),vgmstream->ch[0].streamfile); vgmstream->ch[i].offset = block_offset+0x14; } } else { if(vgmstream->coding_type==coding_PSX) { for (i=0;i<vgmstream->channels;i++) vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2)); } else { for (i=0;i<vgmstream->channels;i++) { if(vgmstream->coding_type==coding_PCM16LE_int) vgmstream->ch[i].offset = block_offset+(i*2); else vgmstream->ch[i].offset = block_offset+i; } } vgmstream->current_block_size/=vgmstream->channels; } vgmstream->next_block_offset = vgmstream->current_block_offset + (off_t)block_size; }
// OMU is a PS2 .INT file with header ... // found in Alter Echo VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[1024]; int i,channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("omu",filename_extension(filename))) goto fail; /* check header */ if((read_32bitBE(0,streamFile)!=0x4F4D5520) && (read_32bitBE(0x08,streamFile)!=0x46524D54)) goto fail; channel_count = (int)read_8bit(0x14,streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,1); if (!vgmstream) goto fail; /* fill in the vital statistics */ vgmstream->channels=channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); vgmstream->coding_type = coding_PCM16LE; vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2)); vgmstream->interleave_block_size = 0x200; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_OMU; vgmstream->loop_start_sample=0; vgmstream->loop_end_sample=vgmstream->num_samples; /* open the file for reading by each channel */ { for (i=0;i<vgmstream->channels;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=0x40+(i*vgmstream->interleave_block_size); } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* 04SW - found in Driver: Parallel Lines (Wii) */ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; size_t file_size, data_size; /* checks */ /* ".04sw" is just the ID, the real filename inside the file uses .XA */ if (!check_extensions(streamFile,"xa,04sw")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x30345357) /* "04SW" */ goto fail; /* after the ID goes a semi-standard DSP header */ if (read_32bitBE(0x10,streamFile) != 0) goto fail; /* should be non looping */ loop_flag = 0; /* not in header it seems so just dual header check */ channel_count = (read_32bitBE(0x04,streamFile) == read_32bitBE(0x64,streamFile)) ? 2 : 1; start_offset = read_32bitBE(0x04 + 0x60*channel_count,streamFile); file_size = get_streamfile_size(streamFile); data_size = read_32bitBE(0x04 + 0x60*channel_count + 0x04,streamFile); if (data_size+start_offset != file_size) goto fail; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); vgmstream->num_samples = read_32bitBE(0x04,streamFile); vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; vgmstream->interleave_block_size = 0x8000; vgmstream->interleave_last_block_size = (read_32bitBE(0x08,streamFile) / 2 % vgmstream->interleave_block_size + 7) / 8 * 8; dsp_read_coefs_be(vgmstream,streamFile,0x20, 0x60); /* the initial history offset seems different thatn standard DSP and possibly always zero */ vgmstream->meta_type = meta_WII_04SW; /* the rest of the header has unknown values (several repeats) and the filename */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* LPCM (from Ah! My Goddess (PS2)) */ VGMSTREAM * init_vgmstream_ps2_lpcm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; off_t start_offset; int loop_flag; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("lpcm",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0,streamFile) != 0x4C50434D) /* LPCM */ goto fail; loop_flag = read_32bitLE(0x8,streamFile); channel_count = 2; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x10; vgmstream->channels = channel_count; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_PCM16LE; vgmstream->num_samples = read_32bitLE(0x4,streamFile); if (loop_flag) { vgmstream->loop_start_sample = read_32bitLE(0x8,streamFile); vgmstream->loop_end_sample = read_32bitLE(0xc,streamFile); } vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 2; vgmstream->meta_type = meta_PS2_LPCM; /* 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; fail: /* clean up anything we may have opened */ if (vgmstream) close_vgmstream(vgmstream); return NULL; }
VGMSTREAM * init_vgmstream_ps3_sgx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; off_t start_offset; int loop_flag = 0; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("sgx",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x53475844) /* "SGXD" */ goto fail; loop_flag = (read_32bitLE(0x44,streamFile) != 0xFFFFFFFF); channel_count = read_8bit(0x29,streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = read_32bitLE(0x4,streamFile); vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x2C,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0xC,streamFile)/16/channel_count*28; if (loop_flag) { vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); vgmstream->loop_end_sample = read_32bitLE(0x48,streamFile); } vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile); vgmstream->meta_type = meta_PS3_SGX; /* 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; }
/* ADP (from Balls of Steel) */ VGMSTREAM * init_vgmstream_bos_adp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("adp",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x41445021) /* "ADP!" */ goto fail; loop_flag = (-1 != read_32bitLE(0x08,streamFile)); channel_count = 1; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x18; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->coding_type = coding_DVI_IMA; vgmstream->num_samples = read_32bitLE(0x04,streamFile); if (loop_flag) { vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; } vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_BOS_ADP; /* open the file for reading */ { STREAMFILE * file; file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!file) goto fail; vgmstream->ch[0].streamfile = file; vgmstream->ch[0].channel_start_offset= vgmstream->ch[0].offset=start_offset; // 0x10, 0x12 - both initial history? //vgmstream->ch[0].adpcm_history1_32 = read_16bitLE(0x10,streamFile); // 0x14 - initial step index? //vgmstream->ch[0].adpcm_step_index = read_32bitLE(0x14,streamFile); } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* The real work is done by libacm */ VGMSTREAM * init_vgmstream_acm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; ACMStream *acm_stream = NULL; mus_acm_codec_data *data; char filename[260]; int loop_flag = 0; int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("acm",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x0,streamFile) != 0x97280301) goto fail; data = calloc(1,sizeof(mus_acm_codec_data)); if (!data) goto fail; data->files = calloc(1,sizeof(ACMStream *)); if (!data->files) { free(data); data = NULL; goto fail; } /* gonna do this a little backwards, open and parse the file before creating the vgmstream */ if (acm_open_decoder(&acm_stream,streamFile,filename) != ACM_OK) { goto fail; } channel_count = acm_stream->info.channels; vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->channels = channel_count; vgmstream->sample_rate = acm_stream->info.rate; vgmstream->coding_type = coding_ACM; vgmstream->num_samples = acm_stream->total_values / acm_stream->info.channels; vgmstream->layout_type = layout_acm; vgmstream->meta_type = meta_ACM; data->file_count = 1; data->current_file = 0; data->files[0] = acm_stream; /*data->end_file = -1;*/ vgmstream->codec_data = data; return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* JSTM (.STM (renamed .JSTM) from Tantei Jinguji Saburo - Kind of Blue) */ VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset = 0x20; int loop_flag; int channel_count; char filename[PATH_LIMIT]; /* check extension */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("stm",filename_extension(filename)) && strcasecmp("jstm",filename_extension(filename))) goto fail; /* check header (JSTM) */ if (read_32bitBE(0x0,streamFile) != 0x4A53544D) goto fail; loop_flag = (read_32bitLE(0x14,streamFile) != 0); channel_count = read_16bitLE(0x4,streamFile); // hmm, don't know what 6 is, one is probably bytes per sample and the // other is channels, but who can say? if (channel_count != read_16bitLE(0x6,streamFile)) goto fail; vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the statistics vitale */ vgmstream->sample_rate = read_32bitLE(0x8,streamFile); vgmstream->coding_type = coding_PCM16LE_XOR_int; vgmstream->num_samples = read_32bitLE(0xC,streamFile)/2/channel_count; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_PS2_JSTM; if (loop_flag) { vgmstream->loop_start_sample=read_32bitLE(0x14,streamFile)/2/channel_count; vgmstream->loop_end_sample=vgmstream->num_samples; } /* 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 + 2*i; vgmstream->ch[i].key_xor = 0x5A5A; } } return vgmstream; fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
static void read_rwav(struct rwav_data * rd) { off_t chunk_table_offset; off_t chunk_table_step; off_t info_chunk; off_t data_chunk; if (rd->big_endian) { /* "RWAV" */ if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574156) return; /* big endian, version 2 */ if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0102) return; chunk_table_offset = rd->offset+0x10; chunk_table_step = 8; } else { /* "CWAV" */ if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x43574156) return; /* little endian, version 2 */ if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFFFE4000 || ( (uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00000102 && (uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00010102 ) ) return; chunk_table_offset = rd->offset+0x18; chunk_table_step = 0xc; } info_chunk = rd->offset+rd->read_32bit(chunk_table_offset,rd->streamFile); /* "INFO" */ if ((uint32_t)read_32bitBE(info_chunk,rd->streamFile)!=0x494e464f) return; data_chunk = rd->offset+rd->read_32bit(chunk_table_offset+chunk_table_step,rd->streamFile); /* "DATA" */ if ((uint32_t)read_32bitBE(data_chunk,rd->streamFile)!=0x44415441) return; rd->start_offset = data_chunk + 8; rd->info_chunk = info_chunk + 8; rd->version = 2; rd->wave_offset = info_chunk - 8; // pretend to have a WAVE return; }
/* .RXW - legacy fake ext/header for poorly split XWH+XWB files generated by old tools (incorrect header/chunk sizes) */ VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int loop_flag=0, channel_count; off_t start_offset; /* check extension, case insensitive */ if (!check_extensions(streamFile,"rxw")) goto fail; /* check RXWS/FORM Header */ if (!((read_32bitBE(0x00,streamFile) == 0x52585753) && (read_32bitBE(0x10,streamFile) == 0x464F524D))) goto fail; loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); channel_count=2; /* Always stereo files */ /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; /* Get loop point values */ if(vgmstream->loop_flag) { vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; } vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_RXWS; start_offset = 0x40; /* open the file for reading */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* STRM - from Final Fantasy Tactics A2 (NDS) */ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; /* checks*/ /* .bin: actual extension * .strm: header id */ if (!check_extensions(streamFile,"bin,strm")) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ read_32bitBE(0x08,streamFile) != 0x494D4120) /* "IMA " */ goto fail; loop_flag = (read_32bitLE(0x20,streamFile) !=0); channel_count = read_32bitLE(0x24,streamFile); start_offset = 0x2C; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset); vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile); vgmstream->meta_type = meta_NDS_STRM_FFTA2; vgmstream->coding_type = coding_FFTA2_IMA; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x80; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* .208 - from Ocean game(s?) [Last Rites (PC)] */ VGMSTREAM * init_vgmstream_208(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count, sample_rate; size_t data_size; /* checks */ if (!check_extensions(streamFile, "208")) goto fail; /* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */ if (!((read_32bitLE(0x04,streamFile) == 0x00 && read_32bitBE(0xcc,streamFile) == 0x1F7D984D) || (read_32bitLE(0x04,streamFile) == 0xF0 && read_32bitBE(0xcc,streamFile) == 0x00000000))) goto fail; start_offset = read_32bitLE(0x00,streamFile); data_size = read_32bitLE(0x0c,streamFile); sample_rate = read_32bitLE(0x34,streamFile); channel_count = read_32bitLE(0x3C,streamFile); /* assumed */ loop_flag = 0; if (start_offset + data_size != get_streamfile_size(streamFile)) goto fail; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_208; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 8); vgmstream->coding_type = coding_PCM8_U; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x1; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* MUSC - from Krome's PS2 games (The Legend of Spyro, Ty the Tasmanian Tiger) */ VGMSTREAM * init_vgmstream_musc(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; int loop_flag, channel_count; off_t start_offset; size_t data_size; /* .mus is the real extension, .musc is the header ID */ if (!check_extensions(streamFile,"mus,musc")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x4D555343) /* "MUSC" */ goto fail; start_offset = read_32bitLE(0x10,streamFile); data_size = read_32bitLE(0x14,streamFile); if (start_offset + data_size != get_streamfile_size(streamFile)) goto fail; /* always does full loops unless it ends in silence */ loop_flag = read_32bitBE(get_streamfile_size(streamFile) - 0x10,streamFile) != 0x0C000000; channel_count = 2; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = (uint16_t)read_16bitLE(0x06,streamFile); vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->meta_type = meta_MUSC; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile) / 2; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
VGMSTREAM * init_vgmstream_xbox_stma(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; int loop_flag=0; int channel_count; int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("stma",filename_extension(filename))) goto fail; if(read_32bitBE(0x0,streamFile)!=0x53544D41) goto fail; loop_flag = ((read_32bitLE(0x20,streamFile)==1) || (read_32bitLE(0x18,streamFile)>read_32bitLE(0x1C,streamFile))); /* Seems that the loop flag is not allways well defined */ /* Some of the tracks should loop, but without flag set */ channel_count=read_32bitLE(0x14,streamFile); /* 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(0x0C,streamFile); vgmstream->coding_type = coding_INT_DVI_IMA; vgmstream->num_samples = read_32bitLE(0x18,streamFile)*2/vgmstream->channels; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size=0x40; vgmstream->meta_type = meta_XBOX_STMA; if(loop_flag) { vgmstream->loop_start_sample=read_32bitLE(0x24,streamFile); vgmstream->loop_end_sample=vgmstream->num_samples; } /* open the file for reading by each channel */ { for (i=0;i<channel_count;i++) { vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36); vgmstream->ch[i].offset = 0x800+(i*vgmstream->interleave_block_size); if (!vgmstream->ch[i].streamfile) goto fail; } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* MIB+MIH - SCEE MultiStream interleaved bank (header+data) [namCollection: Ace Combat 2 (PS2), Rampage: Total Destruction (PS2)] */ VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * streamHeader = NULL; off_t start_offset; size_t data_size, frame_size, frame_last, frame_count; int channel_count, loop_flag; /* check extension */ if (!check_extensions(streamFile, "mib")) goto fail; streamHeader = open_streamfile_by_ext(streamFile,"mih"); if (!streamHeader) goto fail; if (read_32bitBE(0x00,streamHeader) != 0x40000000) /* header size */ goto fail; loop_flag = 0; /* MIB+MIH don't PS-ADPCM loop flags */ channel_count = read_32bitLE(0x08,streamHeader); start_offset = 0x00; /* 0x04: padding (0x20, MIH header must be multiple of 0x40) */ frame_last = (uint16_t)read_16bitLE(0x05,streamHeader); frame_size = read_32bitLE(0x10,streamHeader); frame_count = read_32bitLE(0x14,streamHeader); if (frame_count == 0) { /* rarely [Gladius (PS2)] */ frame_count = get_streamfile_size(streamFile) / (frame_size * channel_count); } data_size = frame_count * frame_size; data_size -= frame_last ? (frame_size-frame_last) : 0; /* last frame has less usable data */ data_size *= channel_count; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitLE(0x0C,streamHeader); vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); vgmstream->meta_type = meta_PS2_MIB_MIH; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = frame_size; if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; close_streamfile(streamHeader); return vgmstream; fail: close_streamfile(streamHeader); close_vgmstream(vgmstream); return NULL; }
/* TUN (from LEGO Racers (PC)) */ VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; off_t start_offset; int channel_count; int loop_flag; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("tun",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */ goto fail; channel_count = 2; loop_flag = 0; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x10; vgmstream->channels = channel_count; vgmstream->sample_rate = 22050; vgmstream->coding_type = coding_DVI_IMA; vgmstream->num_samples = (get_streamfile_size(streamFile)) - 0x10; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 1; vgmstream->meta_type = meta_TUN; /* 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; }
/* A2M - from Artificial Mind & Movement games [Scooby-Doo! Unmasked (PS2)] */ VGMSTREAM * init_vgmstream_a2m(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; size_t data_size; int loop_flag, channel_count; /* checks */ if ( !check_extensions(streamFile,"int") ) goto fail; if (read_32bitBE(0x00,streamFile) != 0x41324D00) /* "A2M\0" */ goto fail; if (read_32bitBE(0x04,streamFile) != 0x50533200) /* "PS2\0" */ goto fail; start_offset = 0x30; data_size = get_streamfile_size(streamFile) - start_offset; channel_count = 2; loop_flag = 0; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_A2M; vgmstream->sample_rate = read_32bitBE(0x10,streamFile); vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count); vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x6000; if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* .VAI - from Asobo Studio games [Ratatouille (GC)] */ VGMSTREAM * init_vgmstream_vai(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; size_t data_size; int loop_flag, channel_count; /* checks */ if ( !check_extensions(streamFile,"vai") ) goto fail; start_offset = 0x4060; data_size = get_streamfile_size(streamFile) - start_offset; if (read_32bitBE(0x04,streamFile) != data_size) goto fail; channel_count = 2; loop_flag = 0; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_VAI; vgmstream->sample_rate = read_32bitBE(0x00,streamFile); vgmstream->num_samples = dsp_bytes_to_samples(data_size,channel_count); vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x4000; dsp_read_coefs_be(vgmstream,streamFile,0x0c,0x20); if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
/* ADS in containers */ VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) { VGMSTREAM *vgmstream = NULL; STREAMFILE *temp_streamFile = NULL; off_t subfile_offset; size_t subfile_size; /* checks */ if (!check_extensions(streamFile, "ads")) goto fail; if (read_32bitBE(0x00,streamFile) == 0x41445343 && /* "ADSC" */ read_32bitBE(0x04,streamFile) == 0x01000000) { /* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */ subfile_offset = 0x08; } else if (read_32bitBE(0x00,streamFile) == 0x63617669 && /* "cavi" */ read_32bitBE(0x04,streamFile) == 0x61207374 && /* "a st" */ read_32bitBE(0x08,streamFile) == 0x7265616D) { /* "ream" */ /* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */ subfile_offset = 0x7d8; } else { goto fail; } subfile_size = get_streamfile_size(streamFile) - subfile_offset; temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); if (!temp_streamFile) goto fail; vgmstream = init_vgmstream_ps2_ads(temp_streamFile); close_streamfile(temp_streamFile); return vgmstream; fail: close_streamfile(temp_streamFile); close_vgmstream(vgmstream); return NULL; }
/* B1S (found in 7 Wonders of the Ancient World) */ VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; int channel_count; off_t start_offset; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("b1s",filename_extension(filename))) goto fail; if ((read_32bitLE(0x04,streamFile)+0x18) != get_streamfile_size(streamFile)) goto fail; channel_count = read_32bitLE(0x14,streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,0); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x18; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x10,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16/channel_count*28; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile); vgmstream->meta_type = meta_PS2_B1S; /* 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; }
/* multiple streams may share a name, also sometimes won't a the name */ static void get_stream_name(char * stream_name, STREAMFILE *streamFile, int target_stream) { STREAMFILE * streamInfo = NULL; int i, j, total_cues, num_cue = -1; size_t name_size = 0; off_t name_offset = 0x10; streamInfo = open_streamfile_by_ext(streamFile, "sob"); if (!streamInfo) goto end; if (read_32bitBE(0x00,streamInfo) != 0x43544632) /* "CTF2" */ goto end; total_cues = read_32bitLE(0x08,streamInfo); for (i = 0; i < total_cues; i++) { uint32_t flags, num_subsections, subsection_1_size, subsection_2_size; flags = (uint32_t)read_32bitLE(name_offset + 0x00,streamInfo); num_subsections = (uint32_t)read_32bitLE(name_offset + 0x20,streamInfo); subsection_1_size = (flags & 0x00000001) ? 0x40 : 0x00; subsection_1_size +=(flags & 0x00000040) ? 0x20 : 0x00; subsection_2_size = (flags & 0x00000100) ? 0x1c : 0x10; for (j = 0; j < num_subsections; j++) { int num_stream = read_32bitLE(name_offset + 0x2c + subsection_1_size + j*subsection_2_size + 0x08,streamInfo); if (target_stream-1 == num_stream) num_cue = i; } name_offset += 0x2c + subsection_1_size + subsection_2_size * num_subsections; } if (num_cue < 0) goto end; for (i = 0; i < total_cues; i++) { /* 0x00: id */ name_size = read_32bitLE(name_offset + 0x04,streamInfo); /* non null-terminated */ if (i == num_cue) { name_offset += 0x08; break; } name_offset += 0x08 + name_size; } if (name_size > STREAM_NAME_SIZE-1) name_size = STREAM_NAME_SIZE-1; read_string(stream_name,name_size+1, name_offset,streamInfo); end: if (streamInfo) close_streamfile(streamInfo); }
/* Maxis XA - found in Sim City 3000 (PC) */ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; /* check extension, case insensitive */ if (!check_extensions(streamFile,"xa")) goto fail; /* check header */ if ((read_32bitBE(0x00,streamFile) != 0x58414900) && /* "XAI\0" */ (read_32bitBE(0x00,streamFile) != 0x58414A00)) /* "XAJ\0" (some odd song uses this, no apparent diffs) */ goto fail; loop_flag = 0; channel_count = read_16bitLE(0x0A,streamFile); start_offset = 0x18; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count; vgmstream->meta_type = meta_MAXIS_XA; vgmstream->coding_type = coding_MAXIS_XA; vgmstream->layout_type = layout_none; /* open streams */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }