mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-13 15:21:04 +01:00
246 lines
7.3 KiB
C
246 lines
7.3 KiB
C
|
#include "../vgmstream.h"
|
||
|
#include "meta.h"
|
||
|
#include "../util.h"
|
||
|
|
||
|
typedef struct _AIXSTREAMFILE
|
||
|
{
|
||
|
STREAMFILE sf;
|
||
|
STREAMFILE *real_file;
|
||
|
off_t start_physical_offset;
|
||
|
off_t current_physical_offset;
|
||
|
off_t current_logical_offset;
|
||
|
off_t current_block_size;
|
||
|
int stream_id;
|
||
|
} AIXSTREAMFILE;
|
||
|
|
||
|
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
||
|
|
||
|
VGMSTREAM * vgmstream = NULL;
|
||
|
STREAMFILE * streamFileADX = NULL;
|
||
|
char filename[260];
|
||
|
|
||
|
int i;
|
||
|
|
||
|
/* check extension, case insensitive */
|
||
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||
|
if (strcasecmp("aix",filename_extension(filename))) goto fail;
|
||
|
|
||
|
streamFileADX = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||
|
if (!streamFileWAV) {
|
||
|
/* try again, ucase */
|
||
|
for (i=strlen(filenameWAV);i>=0&&filenameWAV[i]!=DIRSEP;i--)
|
||
|
filenameWAV[i]=toupper(filenameWAV[i]);
|
||
|
|
||
|
streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||
|
if (!streamFileWAV) goto fail;
|
||
|
}
|
||
|
|
||
|
/* let the real initer do the parsing */
|
||
|
vgmstream = init_vgmstream_riff(streamFileWAV);
|
||
|
if (!vgmstream) goto fail;
|
||
|
|
||
|
close_streamfile(streamFileWAV);
|
||
|
streamFileWAV = NULL;
|
||
|
|
||
|
/* install loops */
|
||
|
if (!vgmstream->loop_flag) {
|
||
|
vgmstream->loop_flag = 1;
|
||
|
vgmstream->loop_ch = calloc(vgmstream->channels,
|
||
|
sizeof(VGMSTREAMCHANNEL));
|
||
|
if (!vgmstream->loop_ch) goto fail;
|
||
|
}
|
||
|
|
||
|
vgmstream->loop_start_sample = read_32bitLE(0,streamFile);
|
||
|
vgmstream->loop_end_sample = read_32bitLE(4,streamFile);
|
||
|
vgmstream->meta_type = meta_RIFF_WAVE_POS;
|
||
|
|
||
|
return vgmstream;
|
||
|
|
||
|
/* clean up anything we may have opened */
|
||
|
fail:
|
||
|
if (streamFileWAV) close_streamfile(streamFileWAV);
|
||
|
if (vgmstream) close_vgmstream(vgmstream);
|
||
|
return NULL;
|
||
|
}
|
||
|
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
|
||
|
{
|
||
|
size_t sz = 0;
|
||
|
|
||
|
while (length > 0)
|
||
|
{
|
||
|
int read_something = 0;
|
||
|
|
||
|
if (offset >= logical_file_size)
|
||
|
{
|
||
|
return sz;
|
||
|
}
|
||
|
|
||
|
/* read the beginning of the requested block, if we can */
|
||
|
if (offset >= streamfile->current_logical_offset)
|
||
|
{
|
||
|
off_t to_read;
|
||
|
off_t length_available;
|
||
|
|
||
|
length_available =
|
||
|
(streamfile->current_logical_offset+
|
||
|
streamfile->current_block_size) -
|
||
|
offset;
|
||
|
|
||
|
if (length < length_available)
|
||
|
{
|
||
|
to_read = length;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
to_read = length_available;
|
||
|
}
|
||
|
|
||
|
if (to_read > 0)
|
||
|
{
|
||
|
size_t bytes_read;
|
||
|
|
||
|
bytes_read = read_streamfile(dest,
|
||
|
streamfile->current_physical_offset+0x10+
|
||
|
(offset-streamfile->current_logical_offset),
|
||
|
to_read,streamfile->real_file);
|
||
|
|
||
|
sz += bytes_read;
|
||
|
if (bytes_read != to_read)
|
||
|
{
|
||
|
/* an error which we will not attempt to handle here */
|
||
|
return sz;
|
||
|
}
|
||
|
|
||
|
read_something = 1;
|
||
|
|
||
|
dest += bytes_read;
|
||
|
offset += bytes_read;
|
||
|
length -= bytes_read;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!read_something)
|
||
|
{
|
||
|
/* couldn't read anything, must seek */
|
||
|
int found_block = 0;
|
||
|
|
||
|
/* as we have no memory we must start seeking from the beginning */
|
||
|
if (offset < streamfile->current_logical_offset)
|
||
|
{
|
||
|
streamfile->current_logical_offset = 0;
|
||
|
streamfile->current_block_size = 0;
|
||
|
streamfile->current_physical_offset =
|
||
|
streamfile->start_physical_offset;
|
||
|
}
|
||
|
|
||
|
/* seek ye forwards */
|
||
|
while (!found_block) {
|
||
|
switch (read_32bitBE(streamfile->current_physical_offset,
|
||
|
streamfile->real_file))
|
||
|
{
|
||
|
case 0x41495850: /* AIXP */
|
||
|
if (read_8bitBE(
|
||
|
streamfile->current_physical_offset+8,
|
||
|
streamfile->real_file) ==
|
||
|
streamfile->stream_id)
|
||
|
{
|
||
|
streamfile->current_block_size =
|
||
|
(uint16_t)read_16bitBE(
|
||
|
streamfile->current_physical_offset+0x0a,
|
||
|
streamfile->real_file);
|
||
|
|
||
|
if (offset >= streamfile->current_logical_offset+
|
||
|
streamfile->current_block_size)
|
||
|
{
|
||
|
streamfile->current_logical_offset +=
|
||
|
streamfile->current_block_size;
|
||
|
streamfile->current_physical_offset +=
|
||
|
read_32bitBE(
|
||
|
streamfile->current_physical_offset+0x04,
|
||
|
streamfile->real_file
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case 0x41495846: /* AIXF */
|
||
|
/* shouldn't ever see this */
|
||
|
case 0x41495845: /* AIXE */
|
||
|
/* shouldn't have reached the end o' the line... */
|
||
|
default:
|
||
|
return sz;
|
||
|
break;
|
||
|
} /* end block/chunk type select */
|
||
|
} /* end while !found_block */
|
||
|
} /* end if !read_something */
|
||
|
} /* end while length > 0 */
|
||
|
|
||
|
return sz;
|
||
|
}
|
||
|
|
||
|
static void close_aix(AIXSTREAMFILE *streamfile)
|
||
|
{
|
||
|
free(streamfile);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static size_t get_size_aix(AIXSTREAMFILE *streamfile)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static size_t get_offset_aix(AIXSTREAMFILE *streamfile)
|
||
|
{
|
||
|
return streamfile->current_logical_offset;
|
||
|
}
|
||
|
|
||
|
static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length)
|
||
|
{
|
||
|
strncpy(buffer,length,"ARBITRARY.ADX");
|
||
|
buffer[length-1]='\0';
|
||
|
}
|
||
|
|
||
|
static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
|
||
|
{
|
||
|
AIXSTREAMFILE *newfile;
|
||
|
if (strcmp(filename,"ARBITRARY.ADX"))
|
||
|
return NULL;
|
||
|
|
||
|
newfile = malloc(sizeof(AIXSTREAMFILE));
|
||
|
if (!newfile)
|
||
|
return NULL;
|
||
|
memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE));
|
||
|
return newfile;
|
||
|
}
|
||
|
|
||
|
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id);
|
||
|
{
|
||
|
AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE));
|
||
|
if (!streamfile)
|
||
|
return NULL;
|
||
|
|
||
|
/* success, set our pointers */
|
||
|
|
||
|
streamfile->sf.read = (void*)read_aix;
|
||
|
streamfile->sf.get_size = (void*)get_size_aix;
|
||
|
streamfile->sf.get_offset = (void*)get_offset_aix;
|
||
|
streamfile->sf.get_name = (void*)get_name_aix;
|
||
|
streamfile->sf.get_realname = (void*)get_name_aix;
|
||
|
streamfile->sf.open = (void*)open_aix_impl;
|
||
|
streamfile->sf.close = (void*)close_aix;
|
||
|
#ifdef PROFILE_STREAMFILE
|
||
|
streamfile->sf.get_bytes_read = NULL;
|
||
|
streamfile->sf.get_error_count = NULL;
|
||
|
#endif
|
||
|
|
||
|
streamfile->real_file = file;
|
||
|
streamfile->current_physicial_offset =
|
||
|
streamfile->start_physical_offset = start_offset;
|
||
|
streamfile->current_logical_offset = 0;
|
||
|
streamfile->current_block_size = 0;
|
||
|
streamfile->stream_id = stream_id;
|
||
|
|
||
|
return &streamfile->sf;
|
||
|
}
|
||
|
|