mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-21 00:38:45 +01:00
46f333cc8e
It was implemented for Audacious only to open companion NWA files, but current version has no need for it. In case there is some obscure thing that needs it, Audacious's vfs.cc should translate or return realnames transparently, without having to modify other streamfiles.
165 lines
5.8 KiB
C
165 lines
5.8 KiB
C
#ifndef _AIX_STREAMFILE_H_
|
|
#define _AIX_STREAMFILE_H_
|
|
#include "../streamfile.h"
|
|
|
|
/* a streamfile representing a subfile inside another, in blocked AIX format */
|
|
|
|
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;
|
|
|
|
|
|
/*static*/ STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file, off_t start_offset, int stream_id);
|
|
|
|
|
|
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) {
|
|
size_t sz = 0;
|
|
|
|
/*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
|
|
while (length > 0) {
|
|
int read_something = 0;
|
|
|
|
/* read the beginning of the requested block, if we can */
|
|
if (offset >= streamfile->current_logical_offset) {
|
|
off_t to_read;
|
|
off_t length_available;
|
|
|
|
length_available = (streamfile->current_logical_offset + streamfile->current_block_size) - offset;
|
|
|
|
if (length < length_available) {
|
|
to_read = length;
|
|
}
|
|
else {
|
|
to_read = length_available;
|
|
}
|
|
|
|
if (to_read > 0) {
|
|
size_t bytes_read;
|
|
|
|
bytes_read = read_streamfile(dest,
|
|
streamfile->current_physical_offset+0x10 + (offset-streamfile->current_logical_offset),
|
|
to_read,streamfile->real_file);
|
|
|
|
sz += bytes_read;
|
|
if (bytes_read != to_read) {
|
|
return sz; /* an error which we will not attempt to handle here */
|
|
}
|
|
|
|
read_something = 1;
|
|
|
|
dest += bytes_read;
|
|
offset += bytes_read;
|
|
length -= bytes_read;
|
|
}
|
|
}
|
|
|
|
if (!read_something) {
|
|
/* couldn't read anything, must seek */
|
|
int found_block = 0;
|
|
|
|
/* as we have no memory we must start seeking from the beginning */
|
|
if (offset < streamfile->current_logical_offset) {
|
|
streamfile->current_logical_offset = 0;
|
|
streamfile->current_block_size = 0;
|
|
streamfile->current_physical_offset = streamfile->start_physical_offset;
|
|
}
|
|
|
|
/* seek ye forwards */
|
|
while (!found_block) {
|
|
/*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
|
|
switch (read_32bitBE(streamfile->current_physical_offset, streamfile->real_file)) {
|
|
case 0x41495850: /* AIXP */
|
|
if (read_8bit(streamfile->current_physical_offset+8, streamfile->real_file) == streamfile->stream_id) {
|
|
streamfile->current_block_size = (uint16_t)read_16bitBE(streamfile->current_physical_offset+0x0a, streamfile->real_file);
|
|
|
|
if (offset >= streamfile->current_logical_offset+ streamfile->current_block_size) {
|
|
streamfile->current_logical_offset += streamfile->current_block_size;
|
|
}
|
|
else {
|
|
found_block = 1;
|
|
}
|
|
}
|
|
|
|
if (!found_block) {
|
|
streamfile->current_physical_offset += read_32bitBE(streamfile->current_physical_offset+0x04, streamfile->real_file) + 8;
|
|
}
|
|
|
|
break;
|
|
case 0x41495846: /* AIXF */
|
|
/* shouldn't ever see this */
|
|
case 0x41495845: /* AIXE */
|
|
/* shouldn't have reached the end o' the line... */
|
|
default:
|
|
return sz;
|
|
break;
|
|
} /* end block/chunk type select */
|
|
} /* end while !found_block */
|
|
} /* end if !read_something */
|
|
} /* end while length > 0 */
|
|
|
|
return sz;
|
|
}
|
|
|
|
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,"ARBITRARY.ADX",length);
|
|
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->sf;
|
|
}
|
|
|
|
/*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.open = (void*)open_aix_impl;
|
|
streamfile->sf.close = (void*)close_aix;
|
|
|
|
streamfile->real_file = file;
|
|
streamfile->current_physical_offset = start_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;
|
|
}
|
|
|
|
#endif /* _AIX_STREAMFILE_H_ */
|