summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStelios Tsampas <loathingkernel@gmail.com>2017-07-10 20:59:31 +0300
committerStelios Tsampas <loathingkernel@gmail.com>2017-07-16 21:21:14 +0300
commit8f19dd4bc9e8189b3aa28040b2a7ee3fcd977f35 (patch)
tree41555f534e1c6969dba49be55534a1efb050874a
parentd880179b2a3aacae96bb4771a3c9e227ca6d5818 (diff)
Bring cdriso.c up to date to enable CCDDA
-rw-r--r--.gitignore1
-rw-r--r--AUTHORS1
-rw-r--r--configure.ac1
-rw-r--r--libpcsxcore/Makefile.am76
-rwxr-xr-xlibpcsxcore/cdriso.c605
5 files changed, 377 insertions, 307 deletions
diff --git a/.gitignore b/.gitignore
index bde255d1..de17812e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ macosx/build
xcuserdata
macosx/Info.plistvers.plist
*.kdev4
+linux_build.sh
diff --git a/AUTHORS b/AUTHORS
index 32f745b4..69a1215c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -26,6 +26,7 @@ PCSX-Reloaded Authors/Contributors: avlex (Help on xcode project)
edgbla (Root counters, SIO1, various core/plugin fixes)
Firnis (GTE code from PCSX-Revolution Project)
Hopkat (Sound plugin improvements, core fixes)
+ iSage (compressed CD-DA, migration to CMake)
Gabriele Gorla (MDEC decoder)
MaddTheSane (Various bugfixes)
maggix (Snow Leopard compile fix)
diff --git a/configure.ac b/configure.ac
index 1aff4c41..6f8166a6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -177,6 +177,7 @@ if test "$BUILD_CCDDA" = "yes"; then
AC_CHECK_LIB([avcodec], [main], [LIBS="$LIBS -lavcodec"], AC_MSG_ERROR("No avcodec library"))
AC_CHECK_LIB([avutil], [main], [LIBS="$LIBS -lavutil"], AC_MSG_ERROR("No avutil library"))
AC_CHECK_LIB([avformat], [main], [LIBS="$LIBS -lavformat"], AC_MSG_ERROR("No avformat library"))
+ AC_CHECK_LIB([swresample], [main], [LIBS="$LIBS -lswresample"], AC_MSG_ERROR("No swresample library"))
#AC_CHECK_LIB(avcodec ,[main],AC_DEFINE([HAVE_LIBAVCODEC], [1], [ ]),AC_MSG_ERROR([$errormsgl]))
#AC_CHECK_LIB(swscale ,[main],AC_DEFINE([HAVE_LIBSWSCALE], [1], [ ]),AC_MSG_ERROR([$errormsgl]), [-lavutil])
#AC_CHECK_LIB(avdevice ,[main],AC_DEFINE([HAVE_LIBAVDEVICE], [1], [ ]),AC_MSG_ERROR([$errormsgl]), [-lavcodec -lavutil -lavformat])
diff --git a/libpcsxcore/Makefile.am b/libpcsxcore/Makefile.am
index f46d2df8..ee585ab7 100644
--- a/libpcsxcore/Makefile.am
+++ b/libpcsxcore/Makefile.am
@@ -4,25 +4,25 @@ AM_CPPFLAGS = -DLOCALE_DIR=\"${datadir}/locale/\" \
noinst_LIBRARIES = libpcsxcore.a
libpcsxcore_a_SOURCES = \
- psxbios.c \
- cdrom.c \
- psxcounters.c \
- psxdma.c \
- disr3000a.c \
- gpu.c \
- gpu.h \
- spu.c \
- sio.c \
- psxhw.c \
- mdec.c \
- psxmem.c \
- misc.c \
- plugins.c \
- decode_xa.c \
- r3000a.c \
- psxinterpreter.c \
- gte.c \
- psxhle.c \
+ psxbios.c \
+ cdrom.c \
+ psxcounters.c \
+ psxdma.c \
+ disr3000a.c \
+ gpu.c \
+ gpu.h \
+ spu.c \
+ sio.c \
+ psxhw.c \
+ mdec.c \
+ psxmem.c \
+ misc.c \
+ plugins.c \
+ decode_xa.c \
+ r3000a.c \
+ psxinterpreter.c \
+ gte.c \
+ psxhle.c \
cdrom.h \
coff.h \
debug.c \
@@ -68,35 +68,35 @@ libpcsxcore_a_SOURCES = \
if ARCH_X86_64
libpcsxcore_a_SOURCES += \
- ix86_64/iGte.h \
- ix86_64/iR3000A-64.c \
- ix86_64/ix86-64.c \
- ix86_64/ix86-64.h \
- ix86_64/ix86_cpudetect.c \
- ix86_64/ix86_fpu.c \
- ix86_64/ix86_3dnow.c \
- ix86_64/ix86_mmx.c \
- ix86_64/ix86_sse.c \
+ ix86_64/iGte.h \
+ ix86_64/iR3000A-64.c \
+ ix86_64/ix86-64.c \
+ ix86_64/ix86-64.h \
+ ix86_64/ix86_cpudetect.c \
+ ix86_64/ix86_fpu.c \
+ ix86_64/ix86_3dnow.c \
+ ix86_64/ix86_mmx.c \
+ ix86_64/ix86_sse.c \
ix86_64/iPGXP.h
else
if ARCH_X86
libpcsxcore_a_SOURCES += \
- ix86/iGte.h \
- ix86/iR3000A.c \
- ix86/ix86.c \
- ix86/ix86.h \
+ ix86/iGte.h \
+ ix86/iR3000A.c \
+ ix86/ix86.c \
+ ix86/ix86.h \
ix86/iPGXP.h
endif
endif
if ARCH_PPC
libpcsxcore_a_SOURCES += \
- ppc/pGte.h \
- ppc/pR3000A.c \
- ppc/ppc.c \
- ppc/ppc.h \
- ppc/ppc_mnemonics.h \
- ppc/reguse.c \
+ ppc/pGte.h \
+ ppc/pR3000A.c \
+ ppc/ppc.c \
+ ppc/ppc.h \
+ ppc/ppc_mnemonics.h \
+ ppc/reguse.c \
ppc/reguse.h
libpcsxcore_a_CCASFLAGS = -x assembler-with-cpp -mregnames -D__POWERPC__
endif
diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c
index 268f1030..4d6c3370 100755
--- a/libpcsxcore/cdriso.c
+++ b/libpcsxcore/cdriso.c
@@ -40,14 +40,11 @@
#ifdef ENABLE_CCDDA
#include "libavcodec/avcodec.h"
#include "libavutil/mathematics.h"
+#include <libavutil/opt.h>
+#include <libavutil/timestamp.h>
#include "libavformat/avformat.h"
+#include <libswresample/swresample.h>
-#define INBUF_SIZE 4096
-#define AUDIO_INBUF_SIZE INBUF_SIZE*4
-#define AUDIO_REFILL_THRESH 4096
-/*#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
- #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
-#endif*/
#endif
unsigned int cdrIsoMultidiskCount;
@@ -88,8 +85,6 @@ static struct {
} *compr_img;
int (*cdimg_read_func)(FILE *f, unsigned int base, void *dest, int sector);
-static int cdread_normal(FILE *f, unsigned int base, void *dest, int sector);
-static int cdread_ecm_decode(FILE *f, unsigned int base, void *dest, int sector);
char* CALLBACK CDR__getDriveLetter(void);
long CALLBACK CDR__configure(void);
@@ -106,9 +101,6 @@ struct trackinfo {
u8 length[3]; // MSF-format
FILE *handle; // for multi-track images CDDA
enum {NONE=0, BIN=1, CCDDA=2
-#ifdef ENABLE_CCDDA1
- ,MP3=AV_CODEC_ID_MP3, APE=AV_CODEC_ID_APE, FLAC=AV_CODEC_ID_FLAC
-#endif
} cddatype; // BIN, WAV, MP3, APE
void* decoded_buffer;
u32 len_decoded_buffer;
@@ -169,17 +161,6 @@ static int get_cdda_type(const char *str)
if (strncmp((str+lenstr-3), "bin", 3) == 0) {
return BIN;
}
-#ifdef ENABLE_CCDDA1
- else if (strncmp((str+lenstr-3), "mp3", 3) == 0) {
- return MP3;
- }
- else if (strncmp((str+lenstr-3), "ape", 3) == 0) {
- return APE;
- }
- else if (strncmp((str+lenstr-4), "flac", 4) == 0) {
- return FLAC;
- }
-#endif
#ifdef ENABLE_CCDDA
else {
return CCDDA;
@@ -196,16 +177,17 @@ static int get_cdda_type(const char *str)
return BIN; // no valid extension or no support; assume bin
}
-static int get_compressed_cdda_track_length(const char* filepath) {
+int get_compressed_cdda_track_length(const char* filepath) {
int seconds = -1;
#ifdef ENABLE_CCDDA
+ av_log_set_level(AV_LOG_QUIET);
av_register_all();
AVFormatContext * inAudioFormat = NULL;
inAudioFormat = avformat_alloc_context();
int errorCode = avformat_open_input(&inAudioFormat, filepath, NULL, NULL);
avformat_find_stream_info(inAudioFormat, NULL);
- seconds = (int)(inAudioFormat->duration/AV_TIME_BASE);
+ seconds = (int)ceil((double)inAudioFormat->duration/(double)AV_TIME_BASE);
avformat_close_input(&inAudioFormat);
#endif
return seconds;
@@ -213,132 +195,208 @@ static int get_compressed_cdda_track_length(const char* filepath) {
#ifdef ENABLE_CCDDA
-static int decode_compressed_cdda_track(FILE* outfile, const char* infilepath, s32 id) {
- AVCodec *codec;
- AVCodecContext *c=NULL;
- AVFormatContext *inAudioFormat = NULL;
- s32 len;
- AVPacket avpkt;
- AVFrame *decoded_frame = NULL;
- s32 got_frame = 0, moreFrames = 1;
- s32 audio_stream_index;
- s32 ret;
-
- //av_init_packet(&avpkt);
-
- avcodec_register_all();
-
- inAudioFormat = avformat_alloc_context();
- int errorCode = avformat_open_input(&inAudioFormat, infilepath, NULL, NULL);
- if (errorCode) {
- SysMessage(_("Audio file opening failed!\n"));
- return errorCode;
+
+int decode_packet(int *got_frame, AVPacket pkt, int audio_stream_idx, AVFrame* frame, AVCodecContext* audio_dec_ctx, void* buf, int* size, SwrContext* swr) {
+ int ret = 0;
+ int decoded = pkt.size;
+ *got_frame = 0;
+
+ if (pkt.stream_index == audio_stream_idx) {
+ ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
+ if (ret < 0) {
+ SysPrintf(_("Error decoding audio frame\n"));
+ return ret;
+ }
+
+ /* Some audio decoders decode only part of the packet, and have to be
+ * called again with the remainder of the packet data.
+ * Sample: fate-suite/lossless-audio/luckynight-partial.shn
+ * Also, some decoders might over-read the packet. */
+
+ decoded = FFMIN(ret, pkt.size);
+
+ if (*got_frame) {
+ size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format);
+ swr_convert(swr, (uint8_t**)&buf, frame->nb_samples, (const uint8_t **)frame->data, frame->nb_samples);
+ (*size)+=(unpadded_linesize*2);
+ }
}
- avformat_find_stream_info(inAudioFormat, NULL);
+ return decoded;
+}
+
+int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) {
+ int ret, stream_index;
+ AVStream *st;
+ AVCodecContext *dec_ctx = NULL;
+ AVCodec *dec = NULL;
+ AVDictionary *opts = NULL;
+
+ ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
- /* select the audio stream */
- ret = av_find_best_stream(inAudioFormat, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
if (ret < 0) {
- avformat_close_input(&inAudioFormat);
- SysMessage(_("Couldn't find any audio stream in file\n"));
+ SysPrintf(_("Could not find %s stream in input file\n"),
+ av_get_media_type_string(type));
return ret;
+ } else {
+ stream_index = ret;
+ st = fmt_ctx->streams[stream_index];
+
+ dec_ctx = st->codec;
+ dec = avcodec_find_decoder(dec_ctx->codec_id);
+ if (!dec) {
+ SysPrintf(_("Failed to find %s codec\n"),
+ av_get_media_type_string(type));
+ return AVERROR(EINVAL);
+ }
+ /* Init the decoders, with or without reference counting */
+ if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
+ SysPrintf(_("Failed to open %s codec\n"),
+ av_get_media_type_string(type));
+ return ret;
+ }
+ *stream_idx = stream_index;
}
- audio_stream_index = ret;
- c = inAudioFormat->streams[audio_stream_index]->codec;
- av_opt_set_int(c, "refcounted_frames", 1, 0);
+ return 0;
+}
- c->sample_fmt = AV_SAMPLE_FMT_S16;
- c->channels = 2;
- c->sample_rate = 44100;
+int decode_compressed_cdda_track(char* buf, char* src_filename, int* size) {
+ AVFormatContext *fmt_ctx = NULL;
+ AVCodecContext *audio_dec_ctx;
+ AVStream *audio_stream = NULL;
+ int audio_stream_idx = -1;
+ AVFrame *frame = NULL;
+ AVPacket pkt;
+ SwrContext *resample_context;
+ int ret = 0, got_frame;
- /* open it */
- if (avcodec_open2(c, codec, NULL) < 0) {
- SysMessage(_("Audio decoder opening failed. Compressed audio support not available.\n"));
- avformat_close_input(&inAudioFormat);
- return 3; // codec open failed
+ av_register_all();
+
+ if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
+ SysPrintf(_("Could not open source file %s\n"), src_filename);
+ return -1;
}
- //http://ffmpeg.org/doxygen/trunk/doc_2examples_2filtering_audio_8c-example.html#a80
- //http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/
- do {
- if ((moreFrames=av_read_frame(inAudioFormat, &avpkt)) < 0) {// returns non-zero on error
- break;
- }
- if (avpkt.stream_index != audio_stream_index) {
- continue;
- }
+ if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
+ SysPrintf(_("Could not find stream information\n"));
+ ret = -1;
+ goto end;
+ }
- if (!decoded_frame) {
- if (!(decoded_frame = avcodec_alloc_frame())) {
- SysMessage(_(" -> Error allocating audio frame buffer. This track will not be available."));
- avformat_close_input(&inAudioFormat);
- av_free(&decoded_frame);
- return 1; // error decoding frame
- }
- } else {
- avcodec_get_frame_defaults(decoded_frame);
- }
- len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
- if (len > 0 && got_frame) {
- /* if a frame has been decoded, output it */
- int data_size = av_samples_get_buffer_size(NULL, c->channels,
- decoded_frame->nb_samples,
- c->sample_fmt, 1);
- //printf ("Channels %i/%i: %i -> %i/%i\n", len, data_size, decoded_frame->sample_rate, c->channels, c->sample_rate);
- fwrite(decoded_frame->data[0], 1, data_size, outfile);
- }
- av_free_packet(&avpkt);
- //avcodec_free_frame(&decoded_frame);
- } while (moreFrames >= 0); // TODO: check for possible leaks
+ if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
+ audio_stream = fmt_ctx->streams[audio_stream_idx];
+ audio_dec_ctx = audio_stream->codec;
+ }
- // file will be closed later on, now just flush it
- fflush(outfile);
+ if (!audio_stream) {
+ SysPrintf(_("Could not find audio stream in the input, aborting\n"));
+ ret = -1;
+ goto end;
+ }
- avformat_close_input(&inAudioFormat);
+ // init and configure resampler
+ resample_context = swr_alloc();
+ if (!resample_context)
+ {
+ SysPrintf(_("Could not allocate resample context"));
+ ret = -1;
+ goto end;
+ }
+ av_opt_set_int(resample_context, "in_channel_layout", audio_dec_ctx->channel_layout, 0);
+ av_opt_set_int(resample_context, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
+ av_opt_set_int(resample_context, "in_sample_rate", audio_dec_ctx->sample_rate, 0);
+ av_opt_set_int(resample_context, "out_sample_rate", 44100, 0);
+ av_opt_set_sample_fmt(resample_context, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);
+ av_opt_set_sample_fmt(resample_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
+ if (swr_init(resample_context) < 0)
+ {
+ SysPrintf(_("Could not open resample context"));
+ ret = -1;
+ goto end;
+ }
- // TODO not sure if all resources are freed...
- //avcodec_close(c);
- //av_free(c);
- //av_free(&decoded_frame);
- return 0;
+
+ frame = av_frame_alloc();
+ if (!frame) {
+ SysPrintf(_("Could not allocate frame\n"));
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
+
+ /* initialize packet, set data to NULL, let the demuxer fill it */
+ av_init_packet(&pkt);
+ pkt.data = NULL;
+ pkt.size = 0;
+
+ /* read frames from the file */
+ while (av_read_frame(fmt_ctx, &pkt) >= 0) {
+ AVPacket orig_pkt = pkt;
+ do {
+ ret = decode_packet(&got_frame, pkt, audio_stream_idx, frame, audio_dec_ctx, buf+(*size), size, resample_context);
+ if (ret < 0)
+ break;
+ pkt.data += ret;
+ pkt.size -= ret;
+ } while (pkt.size > 0);
+ av_packet_unref(&orig_pkt);
+ }
+
+ /* flush cached frames */
+ pkt.data = NULL;
+ pkt.size = 0;
+ do {
+ decode_packet(&got_frame, pkt, audio_stream_idx, frame, audio_dec_ctx, buf+(*size), size, resample_context);
+ } while (got_frame);
+
+end:
+ swr_free(&resample_context);
+ avcodec_close(audio_dec_ctx);
+ avformat_close_input(&fmt_ctx);
+ av_frame_free(&frame);
+ return ret < 0;
}
#endif
-static int do_decode_cdda(struct trackinfo* tri, u32 tracknumber) {
+int do_decode_cdda(struct trackinfo* tri, u32 tracknumber) {
#ifndef ENABLE_CCDDA
- return 4; // support is not compiled in
+ return 0; // support is not compiled in
#else
tri->decoded_buffer = malloc(tri->len_decoded_buffer);
- FILE* decoded_cdda = fmemopen(tri->decoded_buffer, tri->len_decoded_buffer, "wb");
+ memset(tri->decoded_buffer,0,tri->len_decoded_buffer-1);
- if (decoded_cdda == NULL || tri->decoded_buffer == NULL) {
+ if (tri->decoded_buffer == NULL) {
SysMessage(_("Could not allocate memory to decode CDDA TRACK: %s\n"), tri->filepath);
+ fclose(tri->handle); // encoded file handle not needed anymore
+ tri->handle = fmemopen(NULL, 1, "rb"); // change handle to decoded one
+ tri->cddatype = BIN;
+ return 0;
}
fclose(tri->handle); // encoded file handle not needed anymore
int ret;
SysPrintf(_("Decoding audio tr#%u (%s)..."), tracknumber, tri->filepath);
- // decode 2nd input param to 1st output param
- if ((ret=decode_compressed_cdda_track(decoded_cdda, tri->filepath /*tri->handle*/, tri->cddatype)) == 0) {
- int len1 = ftell(decoded_cdda);
- if (len1 > tri->len_decoded_buffer) {
+
+ int len=0;
+
+ if ((ret=decode_compressed_cdda_track(tri->decoded_buffer, tri->filepath, &len)) == 0) {
+ if (len > tri->len_decoded_buffer) {
SysPrintf(_("Buffer overflow..."));
+ SysPrintf(_("Actual %i vs. %i estimated\n"), len, tri->len_decoded_buffer);
+ len = tri->len_decoded_buffer; // we probably segfaulted already, oh well...
}
- //printf("actual %i vs. %i estimated", len1, tri->len_decoded_buffer);
- fclose(decoded_cdda); // close wb file now and will be opened as rb
- tri->handle = fmemopen(tri->decoded_buffer, len1, "rb"); // change handle to decoded one
+
+ tri->handle = fmemopen(tri->decoded_buffer, len, "rb"); // change handle to decoded one
SysPrintf(_("OK\n"), tri->filepath);
}
tri->cddatype = BIN;
- return ret;
+ return len;
#endif
}
// this function tries to get the .toc file of the given .bin
// the necessary data is put into the ti (trackinformation)-array
static int parsetoc(const char *isofile) {
- char tocname[MAXPATHLEN];
+ char tocname[MAXPATHLEN], filename[MAXPATHLEN], *ptr;
FILE *fi;
char linebuf[256], tmp[256], name[256];
char *token;
@@ -377,6 +435,14 @@ static int parsetoc(const char *isofile) {
}
}
+ strcpy(filename, tocname);
+ if ((ptr = strrchr(filename, '/')) == NULL)
+ ptr = strrchr(filename, '\\');
+ if (ptr == NULL)
+ *ptr = 0;
+ else
+ *(ptr + 1) = 0;
+
memset(&ti, 0, sizeof(ti));
cddaBigEndian = TRUE; // cdrdao uses big-endian for CD Audio
@@ -427,6 +493,8 @@ static int parsetoc(const char *isofile) {
else {
sscanf(linebuf, "DATAFILE \"%[^\"]\" %8s", name, time);
tok2msf((char *)&time, (char *)&ti[numtracks].length);
+ strcat(filename, name);
+ ti[numtracks].handle = fopen(filename, "rb");
}
}
else if (!strcmp(token, "FILE")) {
@@ -466,6 +534,8 @@ static int parsetoc(const char *isofile) {
}
}
}
+ if (numtracks > 0)
+ cdHandle = fopen(filename, "rb");
fclose(fi);
@@ -473,160 +543,7 @@ static int parsetoc(const char *isofile) {
}
-int(*cdimg_read_func_archive)(FILE *f, unsigned int base, void *dest, int sector) = NULL;
-#ifdef HAVE_LIBARCHIVE
-#include <archive.h>
-#include <archive_entry.h>
-
-struct archive *a = NULL;
-u32 len_uncompressed_buffer = 0;
-void *cdimage_buffer_mem = NULL;
-FILE* cdimage_buffer = NULL; //cdHandle to store file
-
-int aropen(FILE* fparchive, const char* _fn) {
- s32 r;
- u64 length = 0, length_peek;
- boolean use_temp_file = FALSE; // TODO make a config param
- static struct archive_entry *ae = NULL;
- struct archive_entry *ae_peek;
-
- if (a == NULL && cdimage_buffer == NULL) {
- // We open file twice. First to peek sizes. This nastyness due used interface.
- a = archive_read_new();
- r = archive_read_support_compression_all(a);
- r = archive_read_support_format_all(a);
- //r = archive_read_support_filter_all(a);
- //r = archive_read_support_format_raw(a);
- //r = archive_read_open_FILE(a, archive);
- archive_read_open_filename(a, _fn, 75 * CD_FRAMESIZE_RAW);
- if (r != ARCHIVE_OK) {
- SysPrintf("Archive open failed (%i).\n", r);
- archive_read_free(a);
- a = NULL;
- return -1;
- }
- // Get the biggest file in archive
- while ((r = archive_read_next_header(a, &ae_peek)) == ARCHIVE_OK) {
- length_peek = archive_entry_size(ae_peek);
- //printf("Entry canditate %s %i\n", archive_entry_pathname(ae_peek), length_peek);
- length = MAX(length_peek, length);
- ae = (ae == NULL ? ae_peek : ae);
- }
- archive_read_free(a);
- if (ae == NULL) {
- SysPrintf("Archive entry read failed (%i).\n", r);
- a = NULL;
- return -1;
- }
- //Now really open the file
- a = archive_read_new();
- r = archive_read_support_compression_all(a);
- r = archive_read_support_format_all(a);
- archive_read_open_filename(a, _fn, 75 * CD_FRAMESIZE_RAW);
- while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
- length_peek = archive_entry_size(ae);
- if (length_peek == length) {
- //ae = ae_peek;
- SysPrintf(" -- Selected entry %s %i", archive_entry_pathname(ae), length);
- break;
- }
- }
-
- len_uncompressed_buffer = length ? length : 700 * 1024 * 1024;
- }
-
- if (use_temp_file && (cdimage_buffer == NULL || cdHandle != cdimage_buffer)) {
- cdimage_buffer = fopen("/tmp/pcsxr.tmp.bin", "w+b");
- }
- else if (!use_temp_file && (cdimage_buffer == NULL || cdHandle != cdimage_buffer)) {
- if (cdimage_buffer_mem == NULL && ((cdimage_buffer_mem = malloc(len_uncompressed_buffer)) == NULL)) {
- SysMessage("Could not reserve enough memory for full image buffer.\n");
- exit(3);
- }
- //printf("Memory ok2 %u %p\n", len_uncompressed_buffer, cdimage_buffer_mem);
- cdimage_buffer = fmemopen(cdimage_buffer_mem, len_uncompressed_buffer, "w+b");
- }
- else {
-
- }
-
- if (cdHandle != cdimage_buffer) {
- fclose(cdHandle); // opened thru archive so this not needed anymore
- cdHandle = cdimage_buffer;
- }
-
- return 0;
-}
-
-static int cdread_archive(FILE *f, unsigned int base, void *dest, int sector)
-{
- s32 r;
- size_t size;
- size_t readsize;
- static off_t offset = 0; // w/o read always or static/ftell
- const void *buff;
-
- // If not pointing to archive file but CDDA file or some other track
- if (f != cdHandle) {
- return cdimg_read_func_archive(f, base, dest, sector);
- }
-
- // Jump if already completely read
- if (a != NULL /*&& (ecm_file_detected || sector*CD_FRAMESIZE_RAW <= len_uncompressed_buffer)*/) {
- readsize = (sector + 1) * CD_FRAMESIZE_RAW;
- for (fseek(cdimage_buffer, offset, SEEK_SET); offset < readsize;) {
- r = archive_read_data_block(a, &buff, &size, &offset);
- offset += size;
- SysPrintf("ReadArchive seek:%u(%u) cur:%u(%u)\r", sector, readsize / 1024, offset / CD_FRAMESIZE_RAW, offset / 1024);
- fwrite(buff, size, 1, cdimage_buffer);
- if (r != ARCHIVE_OK) {
- //SysPrintf("End of archive.\n");
- archive_read_free(a);
- a = NULL;
- readsize = offset;
- fflush(cdimage_buffer);
- fseek(cdimage_buffer, 0, SEEK_SET);
- }
- }
- }
- else {
- //SysPrintf("ReadSectorArchSector: %u(%u)\n", sector, sector*CD_FRAMESIZE_RAW);
- }
-
- // TODO what causes req sector to be greater than CD size?
- r = cdimg_read_func_archive(cdimage_buffer, base, dest, sector);
- return r;
-}
-int handlearchive(const char *isoname, s32* accurate_length) {
- u32 read_size = accurate_length ? MSF2SECT(70, 70, 16) : MSF2SECT(0, 0, 16);
- int ret = -1;
- if ((ret = aropen(cdHandle, isoname)) == 0) {
- cdimg_read_func = cdread_archive;
- SysPrintf("[+archive]");
- if (!ecm_file_detected) {
-#ifndef ENABLE_ECM_FULL
- //Detect ECM inside archive
- cdimg_read_func_archive = cdread_normal;
- cdread_archive(cdHandle, 0, cdbuffer, read_size);
- if (handleecm("test.ecm", cdimage_buffer, accurate_length) != -1) {
- cdimg_read_func_archive = cdread_ecm_decode;
- cdimg_read_func = cdread_archive;
- SysPrintf("[+ecm]");
- }
-#endif
- }
- else {
- SysPrintf("[+ecm]");
- }
- }
- return ret;
-}
-#else
-int aropen(FILE* fparchive, const char* _fn) { return -1; }
-static int cdread_archive(FILE *f, unsigned int base, void *dest, int sector) { return -1; }
-int handlearchive(const char *isoname, s32* accurate_length) { return -1; }
-#endif
-
+int handlearchive(const char *isoname, s32* accurate_length);
// this function tries to get the .cue file of the given .bin
// the necessary data is put into the ti (trackinformation)-array
static int parsecue(const char *isofile) {
@@ -717,9 +634,8 @@ static int parsecue(const char *isofile) {
// Send to decoder if not lazy decoding
if (!lazy_decode) {
- do_decode_cdda(&(ti[numtracks]), numtracks);
- fseek(ti[numtracks].handle, 0, SEEK_END);
- file_len = ftell(ti[numtracks].handle) / CD_FRAMESIZE_RAW; // accurate length
+ SysPrintf("\n");
+ file_len = do_decode_cdda(&(ti[numtracks]), numtracks) / CD_FRAMESIZE_RAW;
}
}
}
@@ -1646,6 +1562,157 @@ int handleecm(const char *isoname, FILE* cdh, s32* accurate_length) {
return -1;
}
+int (*cdimg_read_func_archive)(FILE *f, unsigned int base, void *dest, int sector) = NULL;
+#ifdef HAVE_LIBARCHIVE
+#include <archive.h>
+#include <archive_entry.h>
+
+struct archive *a = NULL;
+u32 len_uncompressed_buffer = 0;
+void *cdimage_buffer_mem = NULL;
+FILE* cdimage_buffer = NULL; //cdHandle to store file
+
+int aropen(FILE* fparchive, const char* _fn) {
+ s32 r;
+ u64 length = 0, length_peek;
+ boolean use_temp_file = FALSE; // TODO make a config param
+ static struct archive_entry *ae=NULL;
+ struct archive_entry *ae_peek;
+
+ if (a == NULL && cdimage_buffer == NULL) {
+ // We open file twice. First to peek sizes. This nastyness due used interface.
+ a = archive_read_new();
+// r = archive_read_support_filter_all(a);
+ r = archive_read_support_format_all(a);
+ //r = archive_read_support_filter_all(a);
+ //r = archive_read_support_format_raw(a);
+ //r = archive_read_open_FILE(a, archive);
+ archive_read_open_filename(a, _fn, 75*CD_FRAMESIZE_RAW);
+ if (r != ARCHIVE_OK) {
+ SysPrintf("Archive open failed (%i).\n", r);
+ archive_read_free(a);
+ a = NULL;
+ return -1;
+ }
+ // Get the biggest file in archive
+ while ((r=archive_read_next_header(a, &ae_peek)) == ARCHIVE_OK) {
+ length_peek = archive_entry_size(ae_peek);
+ //printf("Entry canditate %s %i\n", archive_entry_pathname(ae_peek), length_peek);
+ length = MAX(length_peek, length);
+ ae = (ae == NULL ? ae_peek : ae);
+ }
+ archive_read_free(a);
+ if (ae == NULL) {
+ SysPrintf("Archive entry read failed (%i).\n", r);
+ a = NULL;
+ return -1;
+ }
+ //Now really open the file
+ a = archive_read_new();
+// r = archive_read_support_compression_all(a);
+ r = archive_read_support_format_all(a);
+ archive_read_open_filename(a, _fn, 75*CD_FRAMESIZE_RAW);
+ while ((r=archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
+ length_peek = archive_entry_size(ae);
+ if (length_peek == length) {
+ //ae = ae_peek;
+ SysPrintf(" -- Selected entry %s %i", archive_entry_pathname(ae), length);
+ break;
+ }
+ }
+
+ len_uncompressed_buffer = length?length:700*1024*1024;
+ }
+
+ if (use_temp_file && (cdimage_buffer == NULL || cdHandle != cdimage_buffer)) {
+ cdimage_buffer = fopen("/tmp/pcsxr.tmp.bin", "w+b");
+ }
+ else if (!use_temp_file && (cdimage_buffer == NULL || cdHandle != cdimage_buffer)) {
+ if (cdimage_buffer_mem == NULL && ((cdimage_buffer_mem = malloc(len_uncompressed_buffer)) == NULL)) {
+ SysMessage("Could not reserve enough memory for full image buffer.\n");
+ exit(3);
+ }
+ //printf("Memory ok2 %u %p\n", len_uncompressed_buffer, cdimage_buffer_mem);
+ cdimage_buffer = fmemopen(cdimage_buffer_mem, len_uncompressed_buffer, "w+b");
+ } else {
+
+ }
+
+ if (cdHandle != cdimage_buffer) {
+ fclose(cdHandle); // opened thru archive so this not needed anymore
+ cdHandle = cdimage_buffer;
+ }
+
+ return 0;
+}
+
+static int cdread_archive(FILE *f, unsigned int base, void *dest, int sector)
+{
+ s32 r;
+ size_t size;
+ size_t readsize;
+ static off_t offset = 0; // w/o read always or static/ftell
+ const void *buff;
+
+ // If not pointing to archive file but CDDA file or some other track
+ if(f != cdHandle) {
+ return cdimg_read_func_archive(f, base, dest, sector);
+ }
+
+ // Jump if already completely read
+ if (a != NULL /*&& (ecm_file_detected || sector*CD_FRAMESIZE_RAW <= len_uncompressed_buffer)*/) {
+ readsize = (sector+1) * CD_FRAMESIZE_RAW;
+ for (fseek(cdimage_buffer, offset, SEEK_SET); offset < readsize;) {
+ r = archive_read_data_block(a, &buff, &size, &offset);
+ offset += size;
+ SysPrintf("ReadArchive seek:%u(%u) cur:%u(%u)\r", sector, readsize/1024, offset/CD_FRAMESIZE_RAW, offset/1024);
+ fwrite(buff, size, 1, cdimage_buffer);
+ if (r != ARCHIVE_OK) {
+ //SysPrintf("End of archive.\n");
+ archive_read_free(a);
+ a = NULL;
+ readsize = offset;
+ fflush(cdimage_buffer);
+ fseek(cdimage_buffer, 0, SEEK_SET);
+ }
+ }
+ } else {
+ //SysPrintf("ReadSectorArchSector: %u(%u)\n", sector, sector*CD_FRAMESIZE_RAW);
+ }
+
+ // TODO what causes req sector to be greater than CD size?
+ r = cdimg_read_func_archive(cdimage_buffer, base, dest, sector);
+ return r;
+}
+int handlearchive(const char *isoname, s32* accurate_length) {
+ u32 read_size = accurate_length?MSF2SECT(70,70,16) : MSF2SECT(0,0,16);
+ int ret = -1;
+ if ((ret=aropen(cdHandle, isoname)) == 0) {
+ cdimg_read_func = cdread_archive;
+ SysPrintf("[+archive]");
+ if (!ecm_file_detected) {
+#ifndef ENABLE_ECM_FULL
+ //Detect ECM inside archive
+ cdimg_read_func_archive = cdread_normal;
+ cdread_archive(cdHandle, 0, cdbuffer, read_size);
+ if (handleecm("test.ecm", cdimage_buffer, accurate_length) != -1) {
+ cdimg_read_func_archive = cdread_ecm_decode;
+ cdimg_read_func = cdread_archive;
+ SysPrintf("[+ecm]");
+ }
+#endif
+ } else {
+ SysPrintf("[+ecm]");
+ }
+ }
+ return ret;
+}
+#else
+int aropen(FILE* fparchive, const char* _fn) {return -1;}
+static int cdread_archive(FILE *f, unsigned int base, void *dest, int sector) {return -1;}
+int handlearchive(const char *isoname, s32* accurate_length) {return -1;}
+#endif
+
static unsigned char * CALLBACK ISOgetBuffer_compr(void) {
return compr_img->buff_raw[compr_img->sector_in_blk] + 12;
}