mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-21 00:38:45 +01:00
Clean EA 1SNh/EACS (ea_old) and fix some bugs/looping
This commit is contained in:
parent
8f6c76364c
commit
79c5cfab49
10
README.md
10
README.md
@ -224,15 +224,15 @@ This list is not complete and many other files are supported.
|
||||
- .spsd
|
||||
- IMA ADPCM:
|
||||
- .bar (IMA ADPCM)
|
||||
- .dvi (DVI IMA ADPCM)
|
||||
- .pcm/dvi (DVI IMA ADPCM)
|
||||
- .hwas (IMA ADPCM)
|
||||
- .idvi (DVI IMA ADPCM)
|
||||
- .dvi/idvi (DVI IMA ADPCM)
|
||||
- .ivaud (IMA ADPCM)
|
||||
- .myspd (IMA ADPCM)
|
||||
- .strm (IMA ADPCM)
|
||||
- multi:
|
||||
- .aifc (SDX2 DPCM, DVI IMA ADPCM)
|
||||
- .asf/as4 (8/16 bit PCM, EACS IMA ADPCM)
|
||||
- .asf/as4 (8/16 bit PCM, DVI IMA ADPCM)
|
||||
- .ast (GC AFC ADPCM, 16 bit PCM)
|
||||
- .aud (IMA ADPCM, WS DPCM)
|
||||
- .aus (PSX ADPCM, Xbox IMA ADPCM)
|
||||
@ -256,7 +256,7 @@ This list is not complete and many other files are supported.
|
||||
- .seg (Xbox IMA ADPCM, PS2 ADPCM)
|
||||
- .sng/asf/str/eam/aud (8/16 bit PCM, EA-XA ADPCM, PSX ADPCM, GC DSP ADPCM, XBOX IMA ADPCM, MPEG audio, EALayer3)
|
||||
- .strm (NDS IMA ADPCM, 8/16 bit PCM)
|
||||
- .ss7 (EACS IMA ADPCM, IMA ADPCM)
|
||||
- .sb0..7 (Ubi IMA ADPCM, GC DSP ADPCM, PSX ADPCM, Xbox IMA ADPCM, ATRAC3)
|
||||
- .swav (NDS IMA ADPCM, 8/16 bit PCM)
|
||||
- .xwb (PCM, Xbox IMA ADPCM, MS ADPCM, XMA, XWMA, ATRAC3)
|
||||
- .xwb+xwh (PCM, PSX ADPCM, ATRAC3)
|
||||
@ -279,7 +279,7 @@ This list is not complete and many other files are supported.
|
||||
- .caf (Apple IMA4 ADPCM, others)
|
||||
- .de2 (MS ADPCM)
|
||||
- .hca (CRI High Compression Audio)
|
||||
- .kcey (EACS IMA ADPCM)
|
||||
- .pcm/kcey (DVI IMA ADPCM)
|
||||
- .lsf (LSF ADPCM)
|
||||
- .mc3 (Paradigm MC3 ADPCM)
|
||||
- .mp4/lmp4 (AAC)
|
||||
|
@ -507,8 +507,8 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_ast_blocked, "AST blocked"},
|
||||
{layout_halpst_blocked, "HALPST blocked"},
|
||||
{layout_xa_blocked, "CD-ROM XA"},
|
||||
{layout_ea_blocked, "Electronic Arts SCxx blocked"},
|
||||
{layout_eacs_blocked, "Electronic Arts EACS blocked"},
|
||||
{layout_ea_blocked, "blocked (EA SCHl)"},
|
||||
{layout_blocked_ea_1snh, "blocked (EA 1SNh)"},
|
||||
{layout_caf_blocked, "CAF blocked"},
|
||||
{layout_wsi_blocked, ".wsi blocked"},
|
||||
{layout_xvas_blocked, ".xvas blocked"},
|
||||
@ -628,9 +628,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_HGC1, "Knights of the Temple 2 hgC1 Header"},
|
||||
{meta_AUS, "Capcom AUS Header"},
|
||||
{meta_RWS, "RenderWare RWS header"},
|
||||
{meta_EACS_PC, "Electronic Arts EACS header (PC)"},
|
||||
{meta_EACS_PSX, "Electronic Arts EACS header (PSX)"},
|
||||
{meta_EACS_SAT, "Electronic Arts EACS header (SATURN)"},
|
||||
{meta_EA_1SNH, "Electronic Arts 1SNh/EACS header"},
|
||||
{meta_SL3, "SL3 Header"},
|
||||
{meta_FSB1, "FMOD Sample Bank (FSB1) Header"},
|
||||
{meta_FSB2, "FMOD Sample Bank (FSB2) Header"},
|
||||
|
@ -3,52 +3,81 @@
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* set up for the block at the given offset */
|
||||
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
off_t block_size=vgmstream->current_block_size;
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
uint32_t id;
|
||||
size_t file_size, block_size = 0, block_header = 0;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
|
||||
|
||||
if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) {
|
||||
block_offset+=0x0C;
|
||||
|
||||
/* find target block ID and skip the rest */
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
while (block_offset < file_size) {
|
||||
id = read_32bitBE(block_offset+0x00,streamFile);
|
||||
block_size = read_32bit(block_offset+0x04,streamFile); /* includes id/size */
|
||||
block_header = 0x0;
|
||||
|
||||
if (id == 0x31534E68) { /* "1SNh" header block found */
|
||||
block_header = read_32bitBE(block_offset+0x08, streamFile) == 0x45414353 ? 0x28 : 0x2c; /* "EACS" */
|
||||
if (block_header < block_size) /* sometimes has data */
|
||||
break;
|
||||
}
|
||||
|
||||
if (id == 0x31534E64) { /* "1SNd" data block found */
|
||||
block_header = 0x08;
|
||||
break;
|
||||
}
|
||||
|
||||
if (id == 0x00000000 || id == 0xFFFFFFFF) { /* EOF: possible? */
|
||||
break;
|
||||
}
|
||||
|
||||
/* any other blocks "1SNl" "1SNe" etc */ //todo parse movie blocks
|
||||
block_offset += block_size;
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
vgmstream->current_block_size = block_size - block_header;
|
||||
|
||||
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_DVI_IMA) {
|
||||
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 {
|
||||
|
||||
/* set new channel offsets and block sizes */
|
||||
switch(vgmstream->coding_type) {
|
||||
case coding_PCM8_int:
|
||||
vgmstream->current_block_size /= vgmstream->channels;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
if(vgmstream->coding_type==coding_PCM16_int)
|
||||
vgmstream->ch[i].offset = block_offset+(i*2);
|
||||
else
|
||||
vgmstream->ch[i].offset = block_offset+i;
|
||||
vgmstream->ch[i].offset = block_offset + block_header + i;
|
||||
}
|
||||
}
|
||||
vgmstream->current_block_size/=vgmstream->channels;
|
||||
break;
|
||||
|
||||
case coding_PCM16_int:
|
||||
vgmstream->current_block_size /= vgmstream->channels;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = block_offset + block_header + (i*2);
|
||||
}
|
||||
break;
|
||||
|
||||
case coding_PSX:
|
||||
vgmstream->current_block_size /= vgmstream->channels;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = block_offset + block_header + i*vgmstream->current_block_size;
|
||||
}
|
||||
break;
|
||||
|
||||
case coding_DVI_IMA:
|
||||
vgmstream->current_block_size -= 0x14;
|
||||
for(i = 0; i < vgmstream->channels; i++) {
|
||||
off_t adpcm_offset = block_offset + block_header + 0x04;
|
||||
vgmstream->ch[i].adpcm_step_index = read_32bit(adpcm_offset + i*0x04, streamFile);
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_32bit(adpcm_offset + 0x04*vgmstream->channels + i*0x04, streamFile);
|
||||
// todo some demuxed vids don't have ADPCM hist? not sure how to correctly detect
|
||||
vgmstream->ch[i].offset = block_offset + block_header + 0x14;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vgmstream->next_block_offset = vgmstream->current_block_offset +
|
||||
(off_t)block_size;
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
|
@ -1,159 +1,173 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../util.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char szID[4];
|
||||
int dwSampleRate;
|
||||
char bBits;
|
||||
char bChannels;
|
||||
char bCompression;
|
||||
char bType;
|
||||
int dwNumSamples;
|
||||
int dwLoopStart;
|
||||
int dwLoopLength;
|
||||
int dwDataStart;
|
||||
int dwUnknown;
|
||||
} EACSHeader;
|
||||
#define EA_CODEC_PCM 0x00
|
||||
//#define EA_CODEC_??? 0x01 //used in SAT videos
|
||||
#define EA_CODEC_IMA 0x02
|
||||
#define EA_CODEC_PSX 0xFF //fake value
|
||||
|
||||
VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) {
|
||||
typedef struct {
|
||||
int32_t sample_rate;
|
||||
uint8_t bits;
|
||||
uint8_t channels;
|
||||
uint8_t codec;
|
||||
uint8_t type;
|
||||
int32_t num_samples;
|
||||
int32_t loop_start;
|
||||
int32_t loop_end;
|
||||
int32_t loop_start_offset;
|
||||
|
||||
int big_endian;
|
||||
int loop_flag;
|
||||
} ea_header;
|
||||
|
||||
static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset);
|
||||
static void set_ea_1snh_psx_samples(STREAMFILE* streamFile, off_t start_offset, ea_header* ea);
|
||||
|
||||
/* EA 1SNh - from early EA games (~1996, ex. Need for Speed) */
|
||||
VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int channel_count;
|
||||
int loop_flag=0;
|
||||
char little_endian=0;
|
||||
EACSHeader *ea_header = NULL;
|
||||
int32_t samples_count=0;
|
||||
int i;
|
||||
off_t start_offset;
|
||||
ea_header ea = {0};
|
||||
|
||||
/* 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" */
|
||||
/* check extension (.asf/as4: common, cnk: some PS games) */
|
||||
if (!check_extensions(streamFile,"asf,as4,cnk"))
|
||||
goto fail;
|
||||
|
||||
/* check if we are little or big endian */
|
||||
if ((uint32_t)read_32bitBE(4,streamFile)<0x40)
|
||||
little_endian=1;
|
||||
/* check header (first block) */
|
||||
if (read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */
|
||||
goto fail;
|
||||
|
||||
/* check type details */
|
||||
/* use block size as endian marker (Saturn = BE) */
|
||||
ea.big_endian = !(read_32bitLE(0x04,streamFile) < 0x0000FFFF);
|
||||
|
||||
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 */
|
||||
if (!parse_header(streamFile,&ea, 0x08))
|
||||
goto fail;
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,0);
|
||||
if (!vgmstream) goto fail;
|
||||
start_offset = 0x00;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
|
||||
vgmstream->sample_rate = ea_header->dwSampleRate;
|
||||
|
||||
if(ea_header->bCompression==0) {
|
||||
vgmstream->coding_type = coding_PCM16_int;
|
||||
if(ea_header->bBits==1)
|
||||
vgmstream->coding_type = coding_PCM8_int;
|
||||
}
|
||||
else
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
|
||||
vgmstream->layout_type = layout_eacs_blocked;
|
||||
vgmstream->meta_type = meta_EACS_PC;
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(ea.channels, ea.loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
if(little_endian)
|
||||
vgmstream->meta_type = meta_EACS_SAT;
|
||||
vgmstream->sample_rate = ea.sample_rate;
|
||||
vgmstream->num_samples = ea.num_samples;
|
||||
vgmstream->loop_start_sample = ea.loop_start;
|
||||
vgmstream->loop_end_sample = ea.loop_end;
|
||||
|
||||
} else {
|
||||
channel_count=read_32bitLE(0x20,streamFile);
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,0);
|
||||
if (!vgmstream) goto fail;
|
||||
vgmstream->codec_endian = ea.big_endian;
|
||||
vgmstream->layout_type = layout_blocked_ea_1snh;
|
||||
vgmstream->meta_type = meta_EA_1SNH;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type=layout_eacs_blocked;
|
||||
vgmstream->meta_type=meta_EACS_PSX;
|
||||
}
|
||||
switch (ea.codec) {
|
||||
case EA_CODEC_PCM:
|
||||
vgmstream->coding_type = ea.bits==1 ? coding_PCM8_int : coding_PCM16_int;
|
||||
break;
|
||||
|
||||
vgmstream->ea_platform=little_endian;
|
||||
case EA_CODEC_IMA:
|
||||
if (ea.bits!=2) goto fail;
|
||||
vgmstream->coding_type = coding_DVI_IMA; /* high nibble first */
|
||||
break;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
case EA_CODEC_PSX:
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
break;
|
||||
|
||||
default:
|
||||
VGM_LOG("EA: unknown codec 0x%02x\n", ea.codec);
|
||||
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);
|
||||
/* open files; channel offsets are updated below */
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
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);
|
||||
block_update_ea_1snh(start_offset,vgmstream);
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if(ea_header)
|
||||
free(ea_header);
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t offset) {
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE;
|
||||
|
||||
if (read_32bitBE(offset+0x00, streamFile) == 0x45414353) { /* "EACS" */
|
||||
/* PC/SAT EACS subheader */
|
||||
ea->sample_rate = read_32bit(offset+0x04, streamFile);
|
||||
ea->bits = read_8bit(offset+0x08, streamFile);
|
||||
ea->channels = read_8bit(offset+0x09, streamFile);
|
||||
ea->codec = read_8bit(offset+0x0a, streamFile);
|
||||
ea->type = read_8bit(offset+0x0b, streamFile);
|
||||
ea->num_samples = read_32bit(offset+0x0c, streamFile);
|
||||
ea->loop_start = read_32bit(offset+0x10, streamFile);
|
||||
ea->loop_end = read_32bit(offset+0x14, streamFile) + ea->loop_start; /* loop length */
|
||||
/* 0x18: data start? (0x00), 0x1c: pan/volume/etc? (0x7F), rest can be padding/garbage */
|
||||
VGM_ASSERT(ea->type != 0, "EA EACS: unknown type\n"); /* block type? */
|
||||
}
|
||||
else {
|
||||
/* PS subheader */
|
||||
ea->sample_rate = read_32bit(offset+0x00, streamFile);
|
||||
ea->channels = read_8bit(offset+0x18, streamFile);
|
||||
ea->codec = EA_CODEC_PSX;
|
||||
set_ea_1snh_psx_samples(streamFile, 0x00, ea);
|
||||
if (ea->loop_start_offset)/* found offset, now find sample start */
|
||||
set_ea_1snh_psx_samples(streamFile, 0x00, ea);
|
||||
}
|
||||
|
||||
ea->loop_flag = (ea->loop_end > 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get total samples by parsing block headers, needed when EACS isn't present */
|
||||
static void set_ea_1snh_psx_samples(STREAMFILE* streamFile, off_t start_offset, ea_header* ea) {
|
||||
int num_samples = 0, loop_start = 0, loop_end = 0, loop_start_offset = 0;
|
||||
off_t block_offset = start_offset;
|
||||
size_t file_size = get_streamfile_size(streamFile);
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE;
|
||||
|
||||
while (block_offset < file_size) {
|
||||
uint32_t id = read_32bitBE(block_offset+0x00,streamFile);
|
||||
size_t block_size = read_32bit(block_offset+0x04,streamFile); /* includes id/size */
|
||||
|
||||
if (id == 0x31534E68) { /* "1SNh" header block found */
|
||||
size_t block_header = read_32bitBE(block_offset+0x08, streamFile) == 0x45414353 ? 0x28 : 0x2c; /* "EACS" */
|
||||
if (block_header < block_size) /* sometimes has data */
|
||||
num_samples += ps_bytes_to_samples(block_size - block_header, ea->channels);
|
||||
}
|
||||
|
||||
if (id == 0x31534E64) { /* "1SNd" data block found */
|
||||
num_samples += ps_bytes_to_samples(block_size - 0x08, ea->channels);
|
||||
}
|
||||
|
||||
if (id == 0x31534E6C) { /* "1SNl" loop point found */
|
||||
loop_start_offset = read_32bit(block_offset+0x08,streamFile);
|
||||
loop_end = num_samples;
|
||||
}
|
||||
|
||||
if (id == 0x00000000 || id == 0xFFFFFFFF) { /* EOF: possible? */
|
||||
break;
|
||||
}
|
||||
|
||||
/* if there is a loop start offset this was called again just to find it */
|
||||
if (ea->loop_start_offset && ea->loop_start_offset == block_offset) {
|
||||
ea->loop_start = num_samples;
|
||||
return;
|
||||
}
|
||||
|
||||
/* any other blocks "1SNl" "1SNe" etc */ //todo parse movie blocks
|
||||
block_offset += block_size;
|
||||
}
|
||||
|
||||
|
||||
ea->num_samples = num_samples;
|
||||
ea->loop_start = loop_start;
|
||||
ea->loop_end = loop_end;
|
||||
ea->loop_start_offset = loop_start_offset;
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_eacs(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile);
|
||||
|
||||
|
@ -90,7 +90,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_rifx,
|
||||
init_vgmstream_pos,
|
||||
init_vgmstream_nwa,
|
||||
init_vgmstream_eacs,
|
||||
init_vgmstream_ea_1snh,
|
||||
init_vgmstream_xss,
|
||||
init_vgmstream_sl3,
|
||||
init_vgmstream_hgc1,
|
||||
@ -914,7 +914,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
||||
case layout_halpst_blocked:
|
||||
case layout_xa_blocked:
|
||||
case layout_ea_blocked:
|
||||
case layout_eacs_blocked:
|
||||
case layout_blocked_ea_1snh:
|
||||
case layout_caf_blocked:
|
||||
case layout_wsi_blocked:
|
||||
case layout_str_snds_blocked:
|
||||
|
@ -75,15 +75,15 @@ enum { STREAM_NAME_SIZE = 255 }; /* reasonable max */
|
||||
typedef enum {
|
||||
/* PCM */
|
||||
coding_PCM16LE, /* little endian 16-bit PCM */
|
||||
coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor */
|
||||
coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor (for blocks) */
|
||||
coding_PCM16BE, /* big endian 16-bit PCM */
|
||||
coding_PCM16_int, /* 16-bit PCM with sample-level interleave */
|
||||
coding_PCM16_int, /* 16-bit PCM with sample-level interleave (for blocks) */
|
||||
|
||||
coding_PCM8, /* 8-bit PCM */
|
||||
coding_PCM8_int, /* 8-Bit PCM with sample-level interleave */
|
||||
coding_PCM8_int, /* 8-Bit PCM with sample-level interleave (for blocks) */
|
||||
coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */
|
||||
coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave */
|
||||
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */
|
||||
coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave (for blocks) */
|
||||
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave (for blocks) */
|
||||
|
||||
coding_ULAW, /* 8-bit u-Law (non-linear PCM) */
|
||||
coding_ALAW, /* 8-bit a-Law (non-linear PCM) */
|
||||
@ -214,7 +214,7 @@ typedef enum {
|
||||
layout_halpst_blocked,
|
||||
layout_xa_blocked,
|
||||
layout_ea_blocked,
|
||||
layout_eacs_blocked,
|
||||
layout_blocked_ea_1snh,
|
||||
layout_caf_blocked,
|
||||
layout_wsi_blocked,
|
||||
layout_str_snds_blocked,
|
||||
@ -459,9 +459,7 @@ typedef enum {
|
||||
meta_EA_SCHL, /* Electronic Arts SCHl with variable header */
|
||||
meta_EA_SCHL_fixed, /* Electronic Arts SCHl with fixed header */
|
||||
meta_EA_BNK, /* Electronic Arts BNK */
|
||||
meta_EACS_PC, /* Electronic Arts EACS PC */
|
||||
meta_EACS_PSX, /* Electronic Arts EACS PSX */
|
||||
meta_EACS_SAT, /* Electronic Arts EACS SATURN */
|
||||
meta_EA_1SNH, /* Electronic Arts 1SNh/EACS */
|
||||
|
||||
meta_RAW, /* RAW PCM file */
|
||||
|
||||
@ -768,8 +766,6 @@ typedef struct {
|
||||
uint8_t xa_headerless; /* XA ADPCM: headerless XA */
|
||||
int8_t xa_get_high_nibble; /* XA ADPCM: mono/stereo nibble selection (XA state could be simplified) */
|
||||
|
||||
uint8_t ea_platform; /* EA block */
|
||||
|
||||
int32_t ws_output_size; /* WS ADPCM: output bytes for this block */
|
||||
|
||||
int32_t thpNextFrameSize; /* THP */
|
||||
|
Loading…
x
Reference in New Issue
Block a user