/* 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; }
/* 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 }
/* 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; }
/* TRA TRA is an headerless format which can be found on DefJam Rapstar (X360) known extensions : WAVM 2010-12-03 - Fastelbja : First version ... */ VGMSTREAM * init_vgmstream_x360_tra(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("tra",filename_extension(filename))) goto fail; /* No loop on wavm */ loop_flag = 0; /* Always stereo files */ channel_count=2; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ /* allways 2 channels @ 44100 Hz */ vgmstream->channels = 2; vgmstream->sample_rate = 24000; vgmstream->coding_type = coding_DVI_IMA; vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) - ((get_streamfile_size(streamFile)/0x204)*4)); vgmstream->layout_type = layout_tra_blocked; vgmstream->meta_type = meta_X360_TRA; /* open the file for reading by each channel */ { for (i=0;i<channel_count;i++) { vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36); if (!vgmstream->ch[i].streamfile) goto fail; } } tra_block_update(0,vgmstream); return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
int find_chunk(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int size_big_endian, int zero_size_end) { size_t filesize; off_t current_chunk = start_offset; filesize = get_streamfile_size(streamFile); /* read chunks */ while (current_chunk < filesize) { uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); off_t chunk_size = size_big_endian ? read_32bitBE(current_chunk+4,streamFile) : read_32bitLE(current_chunk+4,streamFile); if (chunk_type == chunk_id) { if (out_chunk_offset) *out_chunk_offset = current_chunk+8; if (out_chunk_size) *out_chunk_size = chunk_size; return 1; } /* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */ if (chunk_size == 0 && zero_size_end) return 0; current_chunk += full_chunk_size ? chunk_size : 4+4+chunk_size; } return 0; }
/* FFW (from Freedom Fighters [NGC]) */ VGMSTREAM * init_vgmstream_ffw(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("ffw",filename_extension(filename))) goto fail; loop_flag = 0; channel_count = read_32bitLE(0x11C,streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ start_offset = 0x130; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10C,streamFile); vgmstream->coding_type = coding_PCM16BE; vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; if (channel_count == 1) { vgmstream->layout_type = layout_none; } else { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10000; } vgmstream->meta_type = meta_FFW; /* 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_wvs(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("wvs",filename_extension(filename))) goto fail; if((read_16bitLE(0x0C,streamFile)!=0x69) && (read_16bitLE(0x08,streamFile)!=0x4400) && (read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20)) goto fail; /* Loop seems to be set if offset(0x0A) == 0x472C */ loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C); /* Always stereo files */ channel_count=read_16bitLE(0x0E,streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ /* allways 2 channels @ 44100 Hz */ vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); vgmstream->coding_type = coding_XBOX; vgmstream->num_samples = read_32bitLE(0,streamFile) / 36 * 64 / vgmstream->channels; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_XBOX_WVS; 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 = 0x20; if (!vgmstream->ch[i].streamfile) goto fail; } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) 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; }
/* 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; }
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; }
/* 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; }
VGMSTREAM * init_vgmstream_xbox_matx(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("matx",filename_extension(filename))) goto fail; loop_flag = 0; channel_count=read_16bitLE(0x4,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_16bitLE(0x06,streamFile) & 0xffff; vgmstream->coding_type = coding_XBOX; vgmstream->layout_type = layout_matx_blocked; vgmstream->meta_type = meta_XBOX_MATX; /* open the file for reading by each channel */ { for (i=0;i<channel_count;i++) { vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36); if (!vgmstream->ch[i].streamfile) goto fail; } } /* Calc num_samples */ matx_block_update(0,vgmstream); vgmstream->num_samples=0; do { vgmstream->num_samples += vgmstream->current_block_size/36*64; matx_block_update(vgmstream->next_block_offset,vgmstream); } while (vgmstream->next_block_offset<get_streamfile_size(streamFile)); matx_block_update(0,vgmstream); return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
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; }
/* 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; }
VGMSTREAM * init_vgmstream_ss_stream(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("ss7",filename_extension(filename))) goto fail; loop_flag = 0; channel_count=read_8bit(0x0C,streamFile)+1; /* 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 = 44100; if(channel_count==1) vgmstream->coding_type = coding_IMA; else vgmstream->coding_type = coding_EACS_IMA; vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile) -0x44)* 2 / vgmstream->channels); vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_XBOX_WAVM; vgmstream->get_high_nibble=0; /* 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 = 0x44; vgmstream->ch[i].adpcm_history1_32=(int32_t)read_16bitLE(0x10+i*4,streamFile); vgmstream->ch[i].adpcm_step_index =(int)read_8bit(0x12+i*4,streamFile); if (!vgmstream->ch[i].streamfile) goto fail; } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* Read a line into dst. The source files are MS-DOS style, * separated (not terminated) by CRLF. Return 1 if the full line was * retrieved (if it could fit in dst), 0 otherwise. In any case the result * will be properly terminated. The CRLF will be removed if there is one. * Return the number of bytes read (including CRLF line ending). Note that * this is not the length of the string, and could be larger than the buffer. * *line_done_ptr is set to 1 if the complete line was read into dst, * otherwise it is set to 0. line_done_ptr can be NULL if you aren't * interested in this info. */ size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, STREAMFILE * infile, int *line_done_ptr) { int i; off_t file_length = get_streamfile_size(infile); /* how many bytes over those put in the buffer were read */ int extra_bytes = 0; if (line_done_ptr) *line_done_ptr = 0; for (i=0;i<dst_length-1 && offset+i < file_length;i++) { char in_char = read_8bit(offset+i,infile); /* check for end of line */ if (in_char == 0x0d && read_8bit(offset+i+1,infile) == 0x0a) { extra_bytes = 2; if (line_done_ptr) *line_done_ptr = 1; break; } dst[i]=in_char; } dst[i]='\0'; /* did we fill the buffer? */ if (i==dst_length) { /* did the bytes we missed just happen to be the end of the line? */ if (read_8bit(offset+i,infile) == 0x0d && read_8bit(offset+i+1,infile) == 0x0a) { extra_bytes = 2; /* if so be proud! */ if (line_done_ptr) *line_done_ptr = 1; } } /* did we hit the file end? */ if (offset+i == file_length) { /* then we did in fact finish reading the last line */ if (line_done_ptr) *line_done_ptr = 1; } return i+extra_bytes; }
/* MSA (from Psyvariar -Complete Edition-) */ VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset, datasize, filesize; int loop_flag, channel_count; /* check extension, case insensitive */ if (!check_extensions(streamFile, "msa")) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x00000000) goto fail; loop_flag = 0; channel_count = 2; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; start_offset = 0x14; datasize = read_32bitLE(0x4,streamFile); filesize = get_streamfile_size(streamFile); vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); vgmstream->num_samples = datasize*28/(16*channel_count); vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x4000; vgmstream->meta_type = meta_PS2_MSA; /* MSAs are strangely truncated, so manually calculate samples * data after last usable block is always silence or garbage */ if (datasize > filesize) { off_t usable_size = filesize - start_offset; usable_size -= usable_size % (vgmstream->interleave_block_size*channel_count);/* block-aligned */ vgmstream->num_samples = usable_size * 28 / (16*channel_count); } /* open the file for reading */ if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * chstreamfile; char filename[PATH_LIMIT]; size_t file_size; int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("adp",filename_extension(filename)) && strcasecmp("dtk",filename_extension(filename))) goto fail; /* file size is the only way to determine sample count */ file_size = get_streamfile_size(streamFile); /* .adp files have no header, so all we can do is look for a valid first frame */ if (read_8bit(0,streamFile)!=read_8bit(2,streamFile) || read_8bit(1,streamFile)!=read_8bit(3,streamFile)) goto fail; /* Hopefully we haven't falsely detected something else... */ /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(2,0); /* always stereo, no loop */ if (!vgmstream) goto fail; vgmstream->num_samples = file_size/32*28; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_NGC_DTK; vgmstream->layout_type = layout_dtk_interleave; vgmstream->meta_type = meta_NGC_ADPDTK; /* locality is such that two streamfiles is silly */ chstreamfile = streamFile->open(streamFile,filename,32*0x400); if (!chstreamfile) goto fail; for (i=0;i<2;i++) { vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset = 0; vgmstream->ch[i].streamfile = chstreamfile; } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
VGMSTREAM * init_vgmstream_exakt_sc(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[260]; size_t file_size; /* check extension, case insensitive */ /* this is all we have to go on, SC is completely headerless */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("sc",filename_extension(filename))) goto fail; file_size = get_streamfile_size(streamFile); /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(2,0); if (!vgmstream) goto fail; /* fill in the vital statistics */ vgmstream->num_samples = file_size / 2; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_SASSC; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x100; vgmstream->meta_type = meta_EXAKT_SC; /* open the file for reading by each channel */ { int i; for (i=0;i<2;i++) { vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!vgmstream->ch[i].streamfile) goto fail; vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].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_int(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("int",filename_extension(filename)) && strcasecmp("wp2",filename_extension(filename))) goto fail; if(!strcasecmp("int",filename_extension(filename))) channel_count = 2; else channel_count = 4; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,0); if (!vgmstream) goto fail; /* fill in the vital statistics */ vgmstream->channels=channel_count; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_PCM16LE; vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile)/(vgmstream->channels*2)); vgmstream->interleave_block_size = 0x200; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_RAW; /* 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=i*vgmstream->interleave_block_size; } } return vgmstream; /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; }
/* .SMV - from Cho Aniki Zero (PSP) */ VGMSTREAM * init_vgmstream_smv(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; size_t channel_size, loop_start; /* check extension */ if (!check_extensions(streamFile, "smv")) goto fail; channel_size = read_32bitLE(0x00,streamFile); /* 0x08: number of full interleave blocks */ channel_count = read_16bitLE(0x0a,streamFile); loop_start = read_32bitLE(0x18,streamFile); loop_flag = (loop_start != -1); start_offset = 0x800; if (channel_size * channel_count + start_offset != get_streamfile_size(streamFile)) goto fail; channel_size -= 0x10; /* last value has SPU end frame without flag 0x7 as it should */ /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitLE(0x10, streamFile); vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count); vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start*channel_count, channel_count); vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->meta_type = meta_SMV; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x04, streamFile); vgmstream->interleave_last_block_size = read_32bitLE(0x0c, streamFile); 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; }
/* .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; }
VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset = 0; int channel_count = 2, loop_flag = 0; /* always stereo, no loop */ /* check extension, case insensitive */ if ( !check_extensions(streamFile,"dtk,adp")) goto fail; /* .adp files have no header, and the ext is common, so all we can do is look for valid first frames */ if (check_extensions(streamFile,"adp")) { int i; for (i = 0; i < 10; i++) { /* try a bunch of frames */ if (read_8bit(0x00 + i*0x20,streamFile) != read_8bit(0x02 + i*0x20,streamFile) || read_8bit(0x01 + i*0x20,streamFile) != read_8bit(0x03 + i*0x20,streamFile)) goto fail; } } /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail; vgmstream->num_samples = get_streamfile_size(streamFile) / 32 * 28; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_NGC_DTK; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_NGC_ADPDTK; /* open the file for reading */ if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; fail: 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; }
off_t init_xa_channel(int* channel,STREAMFILE* streamFile) { off_t block_offset=0x44; size_t filelength=get_streamfile_size(streamFile); int8_t currentChannel; int8_t subAudio; // 0 can't be a correct value if(block_offset>=(off_t)filelength) return 0; currentChannel=read_8bit(block_offset-7,streamFile); subAudio=read_8bit(block_offset-6,streamFile); *channel=currentChannel; //if (!((currentChannel==channel) && (subAudio==0x64))) { // block_offset+=2352; // goto begin; //} return block_offset; }
/* 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; }
/* AL" - headerless a-law, found in Conquest of Elysium 3 (PC) */ VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag = 0, channel_count; if ( !check_extensions(streamFile,"al2")) goto fail; channel_count = 2; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = 22050; vgmstream->coding_type = coding_ALAW; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x01; vgmstream->meta_type = meta_PC_AL2; vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), channel_count, 8); if (loop_flag) { vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = vgmstream->num_samples; } start_offset = 0; if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }
STREAMFILE *open_clamp_streamfile(STREAMFILE *streamfile, off_t start, size_t size) { CLAMP_STREAMFILE *this_sf; if (!streamfile || !size) return NULL; if (start + size > get_streamfile_size(streamfile)) return NULL; this_sf = calloc(1,sizeof(CLAMP_STREAMFILE)); if (!this_sf) return NULL; /* set callbacks and internals */ this_sf->sf.read = (void*)clamp_read; this_sf->sf.get_size = (void*)clamp_get_size; this_sf->sf.get_offset = (void*)clamp_get_offset; this_sf->sf.get_name = (void*)clamp_get_name; this_sf->sf.open = (void*)clamp_open; this_sf->sf.close = (void*)clamp_close; this_sf->sf.stream_index = streamfile->stream_index; this_sf->inner_sf = streamfile; this_sf->start = start; this_sf->size = size; return &this_sf->sf; }