diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2011-03-20 14:25:40 +0000 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2011-03-20 14:25:40 +0000 |
commit | ced4b1666765715376058ea16669d18a4f3e68e6 (patch) | |
tree | dd8ca75cfc4f841b82f00ea7b24b849ee277577a | |
parent | 77aa841ba7f4249dceaea6470cb025f976a6e57a (diff) | |
parent | 5f74ef4b65a270a8b985917373bc0e219fa06ecd (diff) | |
download | xine-lib-ced4b1666765715376058ea16669d18a4f3e68e6.tar.gz xine-lib-ced4b1666765715376058ea16669d18a4f3e68e6.tar.bz2 |
Merge from 1.1.
--HG--
rename : src/libxineadec/gsm610/Makefile.am => contrib/gsm610/Makefile.am
rename : src/libxineadec/nosefart/diff_to_nosefart_cvs.patch => contrib/nosefart/diff_to_nosefart_cvs.patch
rename : src/libxineadec/nosefart/nes6502.c => contrib/nosefart/nes6502.c
rename : src/libxineadec/nosefart/nes6502.h => contrib/nosefart/nes6502.h
rename : src/libxineadec/nosefart/nes_apu.c => contrib/nosefart/nes_apu.c
rename : src/libxineadec/nosefart/nes_apu.h => contrib/nosefart/nes_apu.h
rename : src/libxineadec/nosefart/nsf.c => contrib/nosefart/nsf.c
rename : src/libxineadec/nosefart/nsf.h => contrib/nosefart/nsf.h
rename : src/libxineadec/nosefart/types.h => contrib/nosefart/types.h
rename : src/libxineadec/nosefart/version.h => contrib/nosefart/version.h
rename : doc/faq/faq.sgml => doc/faq/faq.docbook
rename : src/libsputext/demux_sputext.c => src/spu_dec/sputext_demuxer.c
rename : src/libxinevdec/image.c => src/video_dec/image.c
37 files changed, 1168 insertions, 357 deletions
@@ -22,7 +22,7 @@ libmad 0.15.1b Miguel Freitas libmpeg2 0.2.1 [*] libmpcdec 1.2.5 libxdg-basedir 0.1.3 Diego Pettenò -nosefart 1.92 Mike Melanson +nosefart 2.7-mls Mike Melanson tvtime 0.9.8.4 Miguel Freitas wine vidix cvs 6/03/05 James Stembridge @@ -75,6 +75,13 @@ xine-lib (1.1.??) 2010-??-?? * Allow use of GraphicsMagick instead of ImageMagick. * Fix build on Debian GNU/kFreeBSD (broken in 1.1.19). * Add a Japanese translation from Takeshi Hamasaki. + * Czech translation update. + * New MinGW-w64 port, various portability fixes. + * MinGW port updates. + * Possibility to disable HW acceleration in directx video output. + * Header stripping support in Matroska demuxer. + * Update nosefart to 2.7-mls (stability with corrupted NSF files). + * Add .ass extension to be recognized as subtitle file. [Bug #123] xine-lib (1.1.19) 2010-07-25 * Handle odd widths properly (for ffmpeg-decoded video). diff --git a/configure.ac b/configure.ac index ae7e0ef44..d646121e2 100644 --- a/configure.ac +++ b/configure.ac @@ -531,8 +531,9 @@ case "$host_or_hostalias" in if test "$WIN32_SYS" = "mingw32"; then WIN32_INCLUDES='-I$(top_srcdir)/win32/include' LIBS="-lwinmm -lwsock32 $LIBS" - GOOM_LIBS="-liberty" LDFLAGS="-Wl,--enable-stdcall-fixup $LDFLAGS" + dnl iberty has been needed only in older versions + AC_CHECK_LIB(iberty, strncomp, [GOOM_LIBS="-liberty"]) AC_SUBST(GOOM_LIBS) fi LDFLAGS="-no-undefined $LDFLAGS" @@ -1305,6 +1306,13 @@ dnl dnl This should be fixed in the libtool package itself as all other dir names dnl there have no trailing slash. dnl --------------------------------------------- +dnl Work around problem due to LTCFLAGS: +dnl +dnl CFLAGS is passed to LTCFLAGS directly from configure instead of Makefiles. +dnl Fixing LTCFLAGS here will help compile xine-list on some crazy platforms. +dnl +dnl It disables multi-pass compilation of xine-list. +dnl --------------------------------------------- dnl Note: Brackets [] must be doubled as they are treated as m4 macro quotes. if test x"$enable_macosx_universal" = x"no"; then @@ -1313,6 +1321,11 @@ else cat libtool | sed -e 's,sys_lib_search_path_spec=.*$,sys_lib_search_path_spec=\"/Developer/SDKs/MacOSX10.4u.sdk/usr/lib\",' > libtool.tmp fi mv -f libtool.tmp libtool + +dnl removing make-specific variable +cat libtool | sed 's/\\$(MULTIPASS_CFLAGS)//' > libtool.tmp +mv -f libtool.tmp libtool + chmod +x libtool XINE_LIB_SUMMARY diff --git a/contrib/nosefart/nes6502.c b/contrib/nosefart/nes6502.c index f1ca80af4..d84bae912 100644 --- a/contrib/nosefart/nes6502.c +++ b/contrib/nosefart/nes6502.c @@ -1117,8 +1117,17 @@ */ /* register push/pull */ -#define PUSH(value) stack_page[S--] = (uint8) (value) -#define PULL() stack_page[++S] +#ifdef NES6502_MEM_ACCESS_CTRL + +# define PUSH(value) stack_push((S--),(value)) +# define PULL() stack_pull((++S)) + +#else + +# define PUSH(value) stack_page[S--] = (uint8) (value) +# define PULL() stack_page[++S] + +#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */ /* Sets the Z and N flags based on given data, taken from precomputed table */ #define SET_NZ_FLAGS(value) P &= ~(N_FLAG | Z_FLAG); \ @@ -1166,50 +1175,194 @@ static uint8 *nes6502_banks[NES6502_NUMBANKS]; static uint8 *ram = NULL; static uint8 *stack_page = NULL; +/* access flag for memory + * $$$ ben : I add this for the playing time calculation. + * Only if compiled with NES6502_MEM_ACCESS. + */ +#ifdef NES6502_MEM_ACCESS_CTRL + +uint8 *acc_nes6502_banks[NES6502_NUMBANKS]; +static uint8 *acc_ram = NULL; +static uint8 *acc_stack_page = NULL; +uint8 nes6502_mem_access = 0; + +/* $$$ ben : + * Set memory access check flags, and store ORed frame global check + * for music time calculation. + */ +static void chk_mem_access(uint8 * access, int flags) +{ + uint8 oldchk = * access; + if ((oldchk&flags) != flags) { + nes6502_mem_access |= flags; + *access = oldchk|flags; + } +} + +INLINE void stack_push(uint8 s, uint8 v) +{ + chk_mem_access(acc_stack_page+s, NES6502_WRITE_ACCESS); + stack_page[s] = v; +} + +INLINE uint8 stack_pull(uint8 s) +{ + chk_mem_access(acc_stack_page+s, NES6502_READ_ACCESS); + return stack_page[s]; +} + +INLINE uint8 zp_read(register uint32 addr) +{ + chk_mem_access(acc_ram+addr, NES6502_READ_ACCESS); + return ram[addr]; +} + +INLINE void zp_write(register uint32 addr, uint8 v) +{ + chk_mem_access(acc_ram+addr, NES6502_WRITE_ACCESS); + ram[addr] = v; +} + +#define ZP_READ(addr) zp_read((addr)) +#define ZP_WRITE(addr, value) zp_write((addr),(value)) + +#define bank_readbyte(address) _bank_readbyte((address), NES6502_READ_ACCESS) +#define bank_readbyte_pc(address) _bank_readbyte((address), NES6502_EXE_ACCESS) + +#else +# define chk_mem_access(access, flags) /* ** Zero-page helper macros */ - #define ZP_READ(addr) ram[(addr)] #define ZP_WRITE(addr, value) ram[(addr)] = (uint8) (value) +#define bank_readbyte(address) _bank_readbyte((address)) +#define bank_readbyte_pc(address) _bank_readbyte((address)) + +#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */ -INLINE uint8 bank_readbyte(register uint32 address) +#ifdef NES6502_MEM_ACCESS_CTRL +int max_access[NES6502_NUMBANKS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +INLINE uint8 _bank_readbyte(register uint32 address, const uint8 flags) +#else +INLINE uint8 _bank_readbyte(register uint32 address) +#endif { ASSERT(nes6502_banks[address >> NES6502_BANKSHIFT]); + +#ifdef NES6502_MEM_ACCESS_CTRL + //printf("chk_mem_access(acc_nes6502_banks[%d] + %d, %d)\n", address>>NES6502_BANKSHIFT, address & NES6502_BANKMASK, flags); + + if((address & NES6502_BANKMASK) > max_access[address>>NES6502_BANKSHIFT]) + { + max_access[address>>NES6502_BANKSHIFT] = address & NES6502_BANKMASK; + //printf("max_access[%d] increased to %d\n", address>>NES6502_BANKSHIFT, max_access[address>>NES6502_BANKSHIFT]); + } +#endif + chk_mem_access(acc_nes6502_banks[address>>NES6502_BANKSHIFT] + + (address & NES6502_BANKMASK), + flags); + return nes6502_banks[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK]; } + INLINE void bank_writebyte(register uint32 address, register uint8 value) { ASSERT(nes6502_banks[address >> NES6502_BANKSHIFT]); + +#ifdef NES6502_MEM_ACCESS_CTRL + //printf("chk_mem_access(acc_nes6502_banks[%d] + %d, %d)\n", address>>NES6502_BANKSHIFT, address & NES6502_BANKMASK, NES6502_WRITE_ACCESS); + + if((address & NES6502_BANKMASK) > max_access[address>>NES6502_BANKSHIFT]) + { + max_access[address>>NES6502_BANKSHIFT] = address & NES6502_BANKMASK; + //printf("max_access[%d] increased to %d\n", address>>NES6502_BANKSHIFT, max_access[address>>NES6502_BANKSHIFT]); + } +#endif + + chk_mem_access(acc_nes6502_banks[address>>NES6502_BANKSHIFT] + + (address & NES6502_BANKMASK), + NES6502_WRITE_ACCESS); + nes6502_banks[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK] = value; } +/* Read a 16bit word */ +#define READ_SNES_16(bank,offset) \ +(\ + (offset) [ (uint8 *) (bank) ] |\ + ((unsigned int)( ((offset)+1) [ (uint8 *) (bank) ] ) << 8)\ +) + INLINE uint32 zp_address(register uint8 address) { - uint8 *x = ram + address; - return (x[1] << 8) | x[0]; + chk_mem_access(acc_ram+address, NES6502_READ_ACCESS); + chk_mem_access(acc_ram+address+1, NES6502_READ_ACCESS); + +#if defined (HOST_LITTLE_ENDIAN) && defined(HOST_UNALIGN_WORD) + /* TODO: this fails if src address is $xFFF */ + /* TODO: this fails if host architecture doesn't support byte alignment */ + /* $$$ ben : DONE */ + return (uint32) (*(uint16 *)(ram + address)); +#elif defined(TARGET_CPU_PPC) + return __lhbrx(ram, address); +#else + return READ_SNES_16(ram,address); +/* uint32 x = (uint32) *(uint16 *)(ram + address); */ +/* return (x << 8) | (x >> 8); */ +//#endif /* TARGET_CPU_PPC */ +#endif /* HOST_LITTLE_ENDIAN */ } INLINE uint32 bank_readaddress(register uint32 address) { - uint8 *x = nes6502_banks[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK); - return (x[1] << 8) | x[0]; + +#ifdef NES6502_MEM_ACCESS_CTRL + { + const unsigned int offset = address & NES6502_BANKMASK; + uint8 * addr = acc_nes6502_banks[address >> NES6502_BANKSHIFT]; + chk_mem_access(addr+offset+0, NES6502_READ_ACCESS); + chk_mem_access(addr+offset+1, NES6502_READ_ACCESS); + } +#endif + +#if defined (HOST_LITTLE_ENDIAN) && defined(HOST_UNALIGN_WORD) + /* TODO: this fails if src address is $xFFF */ + /* TODO: this fails if host architecture doesn't support byte alignment */ + /* $$$ ben : DONE */ + return (uint32) (*(uint16 *)(nes6502_banks[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK))); +#elif defined(TARGET_CPU_PPC) + return __lhbrx(nes6502_banks[address >> NES6502_BANKSHIFT], address & NES6502_BANKMASK); +#else + { + const unsigned int offset = address & NES6502_BANKMASK; + return READ_SNES_16(nes6502_banks[address >> NES6502_BANKSHIFT], offset); + } +/* uint32 x = (uint32) *(uint16 *)(nes6502_banks[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)); */ +/* return (x << 8) | (x >> 8); */ +//#endif /* TARGET_CPU_PPC */ +#endif /* HOST_LITTLE_ENDIAN */ } + /* read a byte of 6502 memory */ static uint8 mem_read(uint32 address) { /* TODO: following cases are N2A03-specific */ /* RAM */ - if (address < 0x800) - return ram[address]; + if (address < 0x800) { + chk_mem_access(acc_ram + address, NES6502_READ_ACCESS); + return ram[address]; + } /* always paged memory */ // else if (address >= 0x6000) - else if (address >= 0x8000) - return bank_readbyte(address); + else if (address >= 0x8000) { + return bank_readbyte(address); + } /* check memory range handlers */ else { @@ -1230,6 +1383,7 @@ static void mem_write(uint32 address, uint8 value) /* RAM */ if (address < 0x800) { + chk_mem_access(acc_ram + address, NES6502_WRITE_ACCESS); ram[address] = value; return; } @@ -1258,11 +1412,19 @@ void nes6502_setcontext(nes6502_context *cpu) ASSERT(cpu); /* Set the page pointers */ - for (loop = 0; loop < NES6502_NUMBANKS; loop++) + for (loop = 0; loop < NES6502_NUMBANKS; loop++) { nes6502_banks[loop] = cpu->mem_page[loop]; +#ifdef NES6502_MEM_ACCESS_CTRL + acc_nes6502_banks[loop] = cpu->acc_mem_page[loop]; +#endif + } ram = nes6502_banks[0]; /* quicker zero-page/RAM references */ stack_page = ram + STACK_OFFSET; +#ifdef NES6502_MEM_ACCESS_CTRL + acc_ram = acc_nes6502_banks[0]; /* quicker zero-page/RAM references */ + acc_stack_page = acc_ram + STACK_OFFSET; +#endif pmem_read = cpu->read_handler; pmem_write = cpu->write_handler; @@ -1283,8 +1445,12 @@ void nes6502_getcontext(nes6502_context *cpu) int loop; /* Set the page pointers */ - for (loop = 0; loop < NES6502_NUMBANKS; loop++) + for (loop = 0; loop < NES6502_NUMBANKS; loop++) { cpu->mem_page[loop] = nes6502_banks[loop]; +#ifdef NES6502_MEM_ACCESS_CTRL + cpu->acc_mem_page[loop] = acc_nes6502_banks[loop]; +#endif + } cpu->read_handler = pmem_read; cpu->write_handler = pmem_write; @@ -1333,7 +1499,14 @@ int nes6502_execute(int remaining_cycles) GET_GLOBAL_REGS(); +#ifdef NES6502_MEM_ACCESS_CTRL + /* reset global memory access for this execute loop. */ + nes6502_mem_access = 0; +#endif + /* Continue until we run out of cycles */ + + while (remaining_cycles > 0) { instruction_cycles = 0; @@ -1373,9 +1546,10 @@ int nes6502_execute(int remaining_cycles) /* Fetch instruction */ //nes6502_disasm(PC, P, A, X, Y, S); - opcode = bank_readbyte(PC++); + opcode = bank_readbyte_pc(PC++); /* Execute instruction */ + switch (opcode) { case 0x00: /* BRK */ @@ -2363,16 +2537,20 @@ void nes6502_setdma(int cycles) dma_cycles += cycles; } +#ifdef NES6502_MEM_ACCESS_CTRL +void nes6502_chk_mem_access(uint8 * access, int flags) +{ + chk_mem_access(access, flags); +} +#endif + /* ** $Log: nes6502.c,v $ -** Revision 1.2 2003/01/09 19:50:03 jkeil -** NSF audio files were crashing on SPARC. -** -** - Define the correct HOST_ENDIAN for SPARC -** - remove unaligned memory accesses +** Revision 1.2 2003/05/01 22:34:19 benjihan +** New NSF plugin ** -** Revision 1.1 2003/01/08 07:04:35 tmmm -** initial import of Nosefart sources +** Revision 1.1 2003/04/08 20:53:00 ben +** Adding more files... ** ** Revision 1.6 2000/07/04 04:50:07 matt ** minor change to includes diff --git a/contrib/nosefart/nes6502.h b/contrib/nosefart/nes6502.h index 9b9be5811..8713304ec 100644 --- a/contrib/nosefart/nes6502.h +++ b/contrib/nosefart/nes6502.h @@ -23,6 +23,9 @@ ** $Id: nes6502.h,v 1.2 2003/12/05 15:55:01 f1rmb Exp $ */ +/* straitm */ +#include "types.h" + /* NOTE: 16-bit addresses avoided like the plague: use 32-bit values ** wherever humanly possible */ @@ -47,6 +50,17 @@ #define NES6502_BANKMASK ((0x10000 / NES6502_NUMBANKS) - 1) +/* Add memory access control flags. This is a ram shadow memory that holds + * for each memory bytes access flags for read, write and execute access. + * The nes6502_mem_access holds all new access (all mode all location). It is + * used to determine if the player has loop in playing time calculation. + */ +#ifdef NES6502_MEM_ACCESS_CTRL +extern uint8 nes6502_mem_access; +# define NES6502_READ_ACCESS 1 +# define NES6502_WRITE_ACCESS 2 +# define NES6502_EXE_ACCESS 4 +#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */ /* P (flag) register bitmasks */ #define N_FLAG 0x80 @@ -87,7 +101,10 @@ typedef struct typedef struct { - uint8 *mem_page[NES6502_NUMBANKS]; /* memory page pointers */ + uint8 * mem_page[NES6502_NUMBANKS]; /* memory page pointers */ +#ifdef NES6502_MEM_ACCESS_CTRL + uint8 * acc_mem_page[NES6502_NUMBANKS]; /* memory access page pointer */ +#endif nes6502_memread *read_handler; nes6502_memwrite *write_handler; int dma_cycles; @@ -110,6 +127,12 @@ extern uint8 nes6502_getbyte(uint32 address); extern uint32 nes6502_getcycles(boolean reset_flag); extern void nes6502_setdma(int cycles); +#ifdef NES6502_MEM_ACCESS_CTRL +extern void nes6502_chk_mem_access(uint8 * access, int flags); +#else +#define nes6502_chk_mem_access(access,flags) +#endif + /* Context get/set */ extern void nes6502_setcontext(nes6502_context *cpu); extern void nes6502_getcontext(nes6502_context *cpu); diff --git a/contrib/nosefart/nes_apu.c b/contrib/nosefart/nes_apu.c index 4a2ed8f4d..474e2ca1a 100644 --- a/contrib/nosefart/nes_apu.c +++ b/contrib/nosefart/nes_apu.c @@ -57,6 +57,11 @@ static int8 noise_long_lut[APU_NOISE_32K]; static int8 noise_short_lut[APU_NOISE_93]; #endif /* !REALTIME_NOISE */ +/* $$$ ben : last error */ +#define SET_APU_ERROR(APU,X) \ +if (APU) (APU)->errstr = "apu: " X; else + +#define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT))) /* vblank length table used for rectangles, triangle, noise */ static const uint8 vbl_length[32] = @@ -102,27 +107,32 @@ const int dmc_clocks[16] = /* ratios of pos/neg pulse for rectangle waves */ static const int duty_lut[4] = { 2, 4, 8, 12 }; -#if 0 /* unused */ -static void apu_setcontext(apu_t *src_apu) + +void apu_setcontext(apu_t *src_apu) { apu = src_apu; + /* $$$ ben reset eoor string here. */ + SET_APU_ERROR(apu,"no error"); } -#endif /* ** Simple queue routines */ #define APU_QEMPTY() (apu->q_head == apu->q_tail) -static void apu_enqueue(apudata_t *d) +static int apu_enqueue(apudata_t *d) { ASSERT(apu); apu->queue[apu->q_head] = *d; apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK; - if (APU_QEMPTY()) + if (APU_QEMPTY()) { log_printf("apu: queue overflow\n"); + SET_APU_ERROR(apu,"queue overflow"); + return -1; + } + return 0; } static apudata_t *apu_dequeue(void) @@ -131,19 +141,32 @@ static apudata_t *apu_dequeue(void) ASSERT(apu); - if (APU_QEMPTY()) - log_printf("apu: queue empty\n"); - + if (APU_QEMPTY()) { + log_printf("apu: queue empty\n"); + SET_APU_ERROR(apu,"queue empty"); + /* $$$ ben : should return 0 ??? */ + } loc = apu->q_tail; apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK; return &apu->queue[loc]; } -void apu_setchan(int chan, boolean enabled) +int apu_setchan(int chan, boolean enabled) { - ASSERT(apu); - apu->mix_enable[chan] = enabled; + const unsigned int max = 6; + int old; + + ASSERT(apu); + if ((unsigned int)chan >= max) { + SET_APU_ERROR(apu,"channel out of range"); + return -1; + } + old = (apu->mix_enable>>chan) & 1; + if (enabled != (boolean)-1) { + apu->mix_enable = (apu->mix_enable & ~(1<<chan)) | ((!!enabled)<<chan); + } + return old; } /* emulation of the 15-bit shift register the @@ -977,13 +1000,13 @@ void apu_process(void *buffer, int num_samples) elapsed_cycles += APU_FROM_FIXED(apu->cycle_rate); accum = 0; - if (apu->mix_enable[0]) accum += apu_rectangle(&apu->rectangle[0]); - if (apu->mix_enable[1]) accum += apu_rectangle(&apu->rectangle[1]); - if (apu->mix_enable[2]) accum += apu_triangle(&apu->triangle); - if (apu->mix_enable[3]) accum += apu_noise(&apu->noise); - if (apu->mix_enable[4]) accum += apu_dmc(&apu->dmc); + if (APU_MIX_ENABLE(0)) accum += apu_rectangle(&apu->rectangle[0]); + if (APU_MIX_ENABLE(1)) accum += apu_rectangle(&apu->rectangle[1]); + if (APU_MIX_ENABLE(2)) accum += apu_triangle(&apu->triangle); + if (APU_MIX_ENABLE(3)) accum += apu_noise(&apu->noise); + if (APU_MIX_ENABLE(4)) accum += apu_dmc(&apu->dmc); - if (apu->ext && apu->mix_enable[5]) accum += apu->ext->process(); + if (apu->ext && APU_MIX_ENABLE(5)) accum += apu->ext->process(); /* do any filtering */ if (APU_FILTER_NONE != apu->filter_type) @@ -1012,11 +1035,12 @@ void apu_process(void *buffer, int num_samples) /* signed 16-bit output, unsigned 8-bit */ if (16 == apu->sample_bits) { - *((int16 *) buffer) = (int16) accum; - buffer = (int16 *) buffer + 1; - } else { - *((uint8 *) buffer) = (accum >> 8) ^ 0x80; - buffer = (int8 *) buffer + 1; + *(int16 *)(buffer) = (int16) accum; + buffer += sizeof(int16); + } + else { + *(uint8 *)(buffer) = (accum >> 8) ^ 0x80; + buffer += sizeof(uint8); } } @@ -1025,10 +1049,18 @@ void apu_process(void *buffer, int num_samples) } /* set the filter type */ -void apu_setfilter(int filter_type) +/* $$$ ben : + * Add a get feature (filter_type == -1) and returns old filter type + */ +int apu_setfilter(int filter_type) { + int old; ASSERT(apu); - apu->filter_type = filter_type; + old = apu->filter_type; + if (filter_type != -1) { + apu->filter_type = filter_type; + } + return old; } void apu_reset(void) @@ -1057,7 +1089,7 @@ void apu_reset(void) apu->ext->reset(); } -static void apu_build_luts(int num_samples) +void apu_build_luts(int num_samples) { int i; @@ -1090,12 +1122,15 @@ static void apu_setactive(apu_t *active) apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo) { apu_t *temp_apu; - int channel; +/* int channel; */ temp_apu = malloc(sizeof(apu_t)); if (NULL == temp_apu) return NULL; + /* $$$ ben : safety net, in case we forgot to init something */ + memset(temp_apu,0,sizeof(apu_t)); + SET_APU_ERROR(temp_apu,"no error"); temp_apu->sample_rate = sample_rate; temp_apu->refresh_rate = refresh_rate; temp_apu->sample_bits = sample_bits; @@ -1114,8 +1149,9 @@ apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean st apu_setactive(temp_apu); apu_reset(); - for (channel = 0; channel < 6; channel++) - apu_setchan(channel, TRUE); + temp_apu->mix_enable = 0x3F; +/* for (channel = 0; channel < 6; channel++) */ +/* apu_setchan(channel, TRUE); */ apu_setfilter(APU_FILTER_LOWPASS); @@ -1137,15 +1173,23 @@ void apu_destroy(apu_t *src_apu) } } -void apu_setext(apu_t *src_apu, apuext_t *ext) +int apu_setext(apu_t *src_apu, apuext_t *ext) { ASSERT(src_apu); + /* $$$ ben : seem cleaner like this */ + if (src_apu->ext) { + src_apu->ext->shutdown(); + } + src_apu->ext = ext; /* initialize it */ if (src_apu->ext) src_apu->ext->init(); + + /* $$$ ben : May be one day extension int () will return error code */ + return 0; } /* this exists for external mixing routines */ diff --git a/contrib/nosefart/nes_apu.h b/contrib/nosefart/nes_apu.h index 09b5842d9..9efbb560e 100644 --- a/contrib/nosefart/nes_apu.h +++ b/contrib/nosefart/nes_apu.h @@ -249,7 +249,7 @@ typedef struct apu_s void *buffer; /* pointer to output buffer */ int num_samples; - boolean mix_enable[6]; + int mix_enable; /* $$$ben : should improve emulation */ int filter_type; int32 cycle_rate; @@ -260,6 +260,9 @@ typedef struct apu_s void (*process)(void *buffer, int num_samples); + /* $$$ ben : last error string */ + const char * errstr; + /* external sound chip */ apuext_t *ext; } apu_t; @@ -272,11 +275,11 @@ extern "C" { /* Function prototypes */ extern apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo); extern void apu_destroy(apu_t *apu); -extern void apu_setext(apu_t *apu, apuext_t *ext); -extern void apu_setfilter(int filter_type); +extern int apu_setext(apu_t *apu, apuext_t *ext); +extern int apu_setfilter(int filter_type); extern void apu_process(void *buffer, int num_samples); extern void apu_reset(void); -extern void apu_setchan(int chan, boolean enabled); +extern int apu_setchan(int chan, boolean enabled); extern int32 apu_getcyclerate(void); extern apu_t *apu_getcontext(void); @@ -286,6 +289,7 @@ extern void apu_write(uint32 address, uint8 value); /* for visualization */ extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits); +extern void apu_setcontext(apu_t *src_apu); #ifdef __cplusplus } diff --git a/contrib/nosefart/nsf.c b/contrib/nosefart/nsf.c index 6bbc96423..69f77546b 100644 --- a/contrib/nosefart/nsf.c +++ b/contrib/nosefart/nsf.c @@ -23,6 +23,7 @@ ** $Id: nsf.c,v 1.4 2006/09/26 00:52:17 dgp85 Exp $ */ + #include <stdio.h> #include <string.h> #include "types.h" @@ -50,25 +51,34 @@ static void nsf_setcontext(nsf_t *nsf) static uint8 read_mirrored_ram(uint32 address) { - return cur_nsf->cpu->mem_page[0][address & 0x7FF]; + nes6502_chk_mem_access(&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF], + NES6502_READ_ACCESS); + return cur_nsf->cpu->mem_page[0][address & 0x7FF]; } static void write_mirrored_ram(uint32 address, uint8 value) { - cur_nsf->cpu->mem_page[0][address & 0x7FF] = value; + nes6502_chk_mem_access(&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF], + NES6502_WRITE_ACCESS); + cur_nsf->cpu->mem_page[0][address & 0x7FF] = value; } /* can be used for both banked and non-bankswitched NSFs */ static void nsf_bankswitch(uint32 address, uint8 value) { int cpu_page; + int roffset; uint8 *offset; cpu_page = address & 0x0F; - offset = (cur_nsf->data - (cur_nsf->load_addr & 0x0FFF)) + (value << 12); + roffset = -(cur_nsf->load_addr & 0x0FFF) + ((int)value << 12); + offset = cur_nsf->data + roffset; nes6502_getcontext(cur_nsf->cpu); cur_nsf->cpu->mem_page[cpu_page] = offset; +#ifdef NES6502_MEM_ACCESS_CTRL + cur_nsf->cpu->acc_mem_page[cpu_page] = offset + cur_nsf->length; +#endif nes6502_setcontext(cur_nsf->cpu); } @@ -248,6 +258,18 @@ static void nsf_inittune(nsf_t *nsf) memset(nsf->cpu->mem_page[6], 0, 0x1000); memset(nsf->cpu->mem_page[7], 0, 0x1000); +#ifdef NES6502_MEM_ACCESS_CTRL + memset(nsf->cpu->acc_mem_page[0], 0, 0x800); + memset(nsf->cpu->acc_mem_page[6], 0, 0x1000); + memset(nsf->cpu->acc_mem_page[7], 0, 0x1000); + memset(nsf->data+nsf->length, 0, nsf->length); +#endif + nsf->cur_frame = 0; +/* nsf->last_access_frame = 0; */ + nsf->cur_frame_end = !nsf->song_frames + ? 0 + : nsf->song_frames[nsf->current_song]; + if (nsf->bankswitched) { /* the first hack of the NSF spec! */ @@ -289,36 +311,81 @@ static void nsf_inittune(nsf_t *nsf) void nsf_frame(nsf_t *nsf) { - //nsf_setcontext(nsf); /* future expansion =) */ + // This is how Matthew Conte left it + //nsf_setcontext(nsf); /* future expansion =) */ + + // This was suggested by Arne Morten Kvarving, who says: +/* Also, I fixed a bug that prevented Nosefart to play multiple tunes at + one time (actually it was just a few missing setcontext calls in the + playback routine, it had a nice TODO commented beside it. You had to set + the cpu and apu contexts not just the nsf context). + + it will affect any player that tries to use nosefart to play more than one + tune at a time. +*/ + nsf_setcontext(nsf); + apu_setcontext(nsf->apu); + nes6502_setcontext(nsf->cpu); /* one frame of NES processing */ nsf_setup_routine(nsf->play_addr, 0, 0); nes6502_execute((int) NES_FRAME_CYCLES); + + ++nsf->cur_frame; +#if defined(NES6502_MEM_ACCESS_CTRL) && 0 + if (nes6502_mem_access) { + uint32 sec = + (nsf->last_access_frame + nsf->playback_rate - 1) / nsf->playback_rate; + nsf->last_access_frame = nsf->cur_frame; + fprintf(stderr,"nsf : memory access [%x] at frame #%u [%u:%02u]\n", + nes6502_mem_access, + nsf->last_access_frame, + sec/60, sec%60); + } +#endif + } /* Deallocate memory */ -static void nes_shutdown(nsf_t *nsf) +void nes_shutdown(nsf_t *nsf) { int i; ASSERT(nsf); - + if (nsf->cpu) { if (nsf->cpu->mem_page[0]) - free(nsf->cpu->mem_page[0]); - for (i = 5; i <= 7; i++) - { - if (nsf->cpu->mem_page[i]) - free(nsf->cpu->mem_page[i]); + { + free(nsf->cpu->mem_page[0]);/*tracks 1 and 2 of lifeforce hang here.*/ + } + for (i = 5; i <= 7; i++) { + if (nsf->cpu->mem_page[i]) + { + free(nsf->cpu->mem_page[i]); + } } + +#ifdef NES6502_MEM_ACCESS_CTRL + if (nsf->cpu->acc_mem_page[0]) + { + free(nsf->cpu->acc_mem_page[0]); + } + for (i = 5; i <= 7; i++) { + if (nsf->cpu->acc_mem_page[i]) + { + free(nsf->cpu->acc_mem_page[i]); + } + } +#endif free(nsf->cpu); } } -void nsf_init(void) +int nsf_init(void) { nes6502_init(); + return 0; } /* Initialize NES CPU, hardware, etc. */ @@ -344,18 +411,27 @@ static int nsf_cpuinit(nsf_t *nsf) return -1; } +#ifdef NES6502_MEM_ACCESS_CTRL + nsf->cpu->acc_mem_page[0] = malloc(0x800); + if (NULL == nsf->cpu->acc_mem_page[0]) + return -1; + /* allocate some space for the NSF "player" MMC5 EXRAM, and WRAM */ + for (i = 5; i <= 7; i++) + { + nsf->cpu->acc_mem_page[i] = malloc(0x1000); + if (NULL == nsf->cpu->acc_mem_page[i]) + return -1; + } +#endif + nsf->cpu->read_handler = nsf_readhandler; nsf->cpu->write_handler = nsf_writehandler; return 0; } -static void nsf_setup(nsf_t *nsf) +static unsigned int nsf_playback_rate(nsf_t *nsf) { - int i; - - nsf->current_song = nsf->start_song; - if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL) { if (nsf->pal_speed) @@ -370,9 +446,17 @@ static void nsf_setup(nsf_t *nsf) else nsf->playback_rate = 60; /* 60 Hz */ } + return 0; +} - nsf->bankswitched = FALSE; +static void nsf_setup(nsf_t *nsf) +{ + int i; + + nsf->current_song = nsf->start_song; + nsf_playback_rate(nsf); + nsf->bankswitched = FALSE; for (i = 0; i < 8; i++) { if (nsf->bankswitch_info[i]) @@ -389,212 +473,551 @@ static void nsf_setup(nsf_t *nsf) #define SWAP_16(x) (((uint16) x >> 8) | (((uint16) x & 0xFF) << 8)) #endif /* !HOST_LITTLE_ENDIAN */ -/* Load a ROM image into memory */ -nsf_t *nsf_load(char *filename, void *source, int length) +/* $$$ ben : find extension. Should be OK with DOS, but not with some + * OS like RiscOS ... */ +static char * find_ext(char *fn) { - FILE *fp = NULL; - char *new_fn = NULL; - nsf_t *temp_nsf; + char * a, * b, * c; + a = strrchr(fn,'.'); + b = strrchr(fn,'/'); + c = strrchr(fn,'\\'); + if (a <= b || a <= c) { + a = 0; + } + return a; +} - if (NULL == filename && NULL == source) - return NULL; - - if (NULL == source) - { - fp = fopen(filename, "rb"); +/* $$$ ben : FILE loader */ +struct nsf_file_loader_t { + struct nsf_loader_t loader; + FILE *fp; + char * fname; + int name_allocated; +}; - /* Didn't find the file? Maybe the .NSF extension was omitted */ - if (NULL == fp) - { - new_fn = malloc(strlen(filename) + 5); - if (NULL == new_fn) - return NULL; - strcpy(new_fn, filename); +static int nfs_open_file(struct nsf_loader_t *loader) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + + floader->name_allocated = 0; + floader->fp = 0; + if (!floader->fname) { + return -1; + } + floader->fp = fopen(floader->fname,"rb"); + if (!floader->fp) { + char * fname, * ext; + ext = find_ext(floader->fname); + if (ext) { + /* There was an extension, so we do not change it */ + return -1; + } + fname = malloc(strlen(floader->fname) + 5); + if (!fname) { + return -1; + } + /* try with .nsf extension. */ + strcpy(fname, floader->fname); + strcat(fname, ".nsf"); + floader->fp = fopen(fname,"rb"); + if (!floader->fp) { + free(fname); + return -1; + } + floader->fname = fname; + floader->name_allocated = 1; + } + return 0; +} - if (NULL == strrchr(new_fn, '.')) - strcat(new_fn, ".nsf"); +static void nfs_close_file(struct nsf_loader_t *loader) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + if (floader->fp) { + fclose(floader->fp); + floader->fp = 0; + } + if (floader->fname && floader->name_allocated) { + free(floader->fname); + floader->fname = 0; + floader->name_allocated = 0; + } +} - fp = fopen(new_fn, "rb"); +static int nfs_read_file(struct nsf_loader_t *loader, void *data, int n) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + int r = fread(data, 1, n, floader->fp); + if (r >= 0) { + r = n-r; + } + return r; +} - if (NULL == fp) - { - log_printf("could not find file '%s'\n", new_fn); - free(new_fn); - return NULL; - } - } - } +static int nfs_length_file(struct nsf_loader_t *loader) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + long save, pos; + save = ftell(floader->fp); + fseek(floader->fp, 0, SEEK_END); + pos = ftell(floader->fp); + fseek(floader->fp, save, SEEK_SET); + return pos; +} - temp_nsf = malloc(sizeof(nsf_t)); - if (NULL == temp_nsf) { - fclose(fp); - free(new_fn); - return NULL; - } +static int nfs_skip_file(struct nsf_loader_t *loader, int n) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + int r; + r = fseek(floader->fp, n, SEEK_CUR); + return r; +} - /* Read in the header */ - if (NULL == source) - fread(temp_nsf, 1, NSF_HEADER_SIZE, fp); - else - memcpy(temp_nsf, source, NSF_HEADER_SIZE); +static const char * nfs_fname_file(struct nsf_loader_t *loader) +{ + struct nsf_file_loader_t * floader = (struct nsf_file_loader_t *)loader; + return floader->fname ? floader->fname : "<null>"; +} - if (memcmp(temp_nsf->id, NSF_MAGIC, 5)) - { - if (NULL == source) - { - log_printf("%s is not an NSF format file\n", new_fn); - fclose(fp); - free(new_fn); - } - nsf_free(&temp_nsf); - return NULL; - } +static struct nsf_file_loader_t nsf_file_loader = { + { + nfs_open_file, + nfs_close_file, + nfs_read_file, + nfs_length_file, + nfs_skip_file, + nfs_fname_file + }, + 0,0,0 +}; + +struct nsf_mem_loader_t { + struct nsf_loader_t loader; + uint8 *data; + unsigned long cur; + unsigned long len; + char fname[32]; +}; - /* fixup endianness */ - temp_nsf->load_addr = SWAP_16(temp_nsf->load_addr); - temp_nsf->init_addr = SWAP_16(temp_nsf->init_addr); - temp_nsf->play_addr = SWAP_16(temp_nsf->play_addr); - temp_nsf->ntsc_speed = SWAP_16(temp_nsf->ntsc_speed); - temp_nsf->pal_speed = SWAP_16(temp_nsf->pal_speed); +static int nfs_open_mem(struct nsf_loader_t *loader) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + if (!mloader->data) { + return -1; + } + mloader->cur = 0; + sprintf(mloader->fname,"<mem(%p,%u)>", + mloader->data, (unsigned int)mloader->len); + return 0; +} - /* we're now at position 80h */ - if (NULL == source) - { - fseek(fp, 0, SEEK_END); - temp_nsf->length = ftell(fp) - NSF_HEADER_SIZE; - } - else - { - temp_nsf->length = length - NSF_HEADER_SIZE; - } +static void nfs_close_mem(struct nsf_loader_t *loader) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + mloader->data = 0; + mloader->cur = 0; + mloader->len = 0; +} - /* Allocate NSF space, and load it up! */ - temp_nsf->data = malloc(temp_nsf->length); - if (NULL == temp_nsf->data) - { - log_printf("error allocating memory for NSF data\n"); - nsf_free(&temp_nsf); - return NULL; - } +static int nfs_read_mem(struct nsf_loader_t *loader, void *data, int n) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + int rem; + if (n <= 0) { + return n; + } + if (!mloader->data) { + return -1; + } + rem = mloader->len - mloader->cur; + if (rem > n) { + rem = n; + } + memcpy(data, mloader->data + mloader->cur, rem); + mloader->cur += rem; + return n - rem; +} - /* seek to end of header, read in data */ - if (NULL == source) - { - fseek(fp, NSF_HEADER_SIZE, SEEK_SET); - fread(temp_nsf->data, temp_nsf->length, 1, fp); +static int nfs_length_mem(struct nsf_loader_t *loader) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + return mloader->len; +} - fclose(fp); +static int nfs_skip_mem(struct nsf_loader_t *loader, int n) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + unsigned long goal = mloader->cur + n; + mloader->cur = (goal > mloader->len) ? mloader->len : goal; + return goal - mloader->cur; +} - if (new_fn) - free(new_fn); - } - else - memcpy(temp_nsf->data, (uint8 *) source + NSF_HEADER_SIZE, length - NSF_HEADER_SIZE); +static const char * nfs_fname_mem(struct nsf_loader_t *loader) +{ + struct nsf_mem_loader_t * mloader = (struct nsf_mem_loader_t *)loader; + return mloader->fname; +} + +static struct nsf_mem_loader_t nsf_mem_loader = { + { nfs_open_mem, nfs_close_mem, nfs_read_mem, nfs_length_mem, nfs_skip_mem }, + 0,0,0 +}; + +nsf_t * nsf_load_extended(struct nsf_loader_t * loader) +{ + nsf_t *temp_nsf = 0; + int length; + char id[6]; + + struct { + uint8 magic[4]; /* always "NESM" */ + uint8 type[4]; /* defines extension type */ + uint8 size[4]; /* extension data size (this struct include) */ + } nsf_file_ext; + + /* no loader ! */ + if (!loader) { + return NULL; + } + + /* Open the "file" */ + if (loader->open(loader) < 0) { + return NULL; + } + + /* Get file size, and exit if there is not enough data for NSF header + * and more since it does not make sens to have header without data. + */ + length = loader->length(loader); + /* For version 2, we do not need file length. just check error later. */ +#if 0 + if (length <= NSF_HEADER_SIZE) { + log_printf("nsf : [%s] not an NSF format file\n", + loader->fname); + goto error; + } +#endif + + /* Read magic */ + if (loader->read(loader, id, 5)) { + log_printf("nsf : [%s] error reading magic number\n", + loader->fname); + goto error; + } + + /* Check magic */ + if (memcmp(id, NSF_MAGIC, 5)) { + log_printf("nsf : [%s] is not an NSF format file\n", + loader->fname); + goto error; + } + + /* $$$ ben : Now the file should be an NSF, we can start allocating. + * first : the nsf struct + */ + temp_nsf = malloc(sizeof(nsf_t)); + + if (NULL == temp_nsf) { + log_printf("nsf : [%s] error allocating nsf header\n", + loader->fname); + goto error; + } + /* $$$ ben : safety net */ + memset(temp_nsf,0,sizeof(nsf_t)); + /* Copy magic ID */ + memcpy(temp_nsf,id,5); + + /* Read header (without MAGIC) */ + if (loader->read(loader, (int8 *)temp_nsf+5, NSF_HEADER_SIZE - 5)) { + log_printf("nsf : [%s] error reading nsf header\n", + loader->fname); + goto error; + } + + /* fixup endianness */ + temp_nsf->load_addr = SWAP_16(temp_nsf->load_addr); + temp_nsf->init_addr = SWAP_16(temp_nsf->init_addr); + temp_nsf->play_addr = SWAP_16(temp_nsf->play_addr); + temp_nsf->ntsc_speed = SWAP_16(temp_nsf->ntsc_speed); + temp_nsf->pal_speed = SWAP_16(temp_nsf->pal_speed); + + /* we're now at position 80h */ + + + /* Here comes the specific codes for spec version 2 */ + + temp_nsf->length = 0; + + if (temp_nsf->version > 1) { + /* Get specified data size in reserved field (3 bytes). */ + temp_nsf->length = 0 + + temp_nsf->reserved[0] + + (temp_nsf->reserved[1]<<8) + + (temp_nsf->reserved[2]<<16); + + } + /* no specified size : try to guess with file length. */ + if (!temp_nsf->length) { + temp_nsf->length = length - NSF_HEADER_SIZE; + } + + if (temp_nsf->length <= 0) { + log_printf("nsf : [%s] not an NSF format file (missing data)\n", + loader->fname); + goto error; + } + + /* Allocate NSF space, and load it up! */ + { + int len = temp_nsf->length; +#ifdef NES6502_MEM_ACCESS_CTRL + /* $$$ twice memory for access control shadow mem. */ + len <<= 1; +#endif + temp_nsf->data = malloc(len); + } + if (NULL == temp_nsf->data) { + log_printf("nsf : [%s] error allocating nsf data\n", + loader->fname); + goto error; + } + + /* Read data */ + if (loader->read(loader, temp_nsf->data, temp_nsf->length)) { + log_printf("nsf : [%s] error reading NSF data\n", + loader->fname); + goto error; + } + + /* Here comes the second part of spec > 1 : get extension */ + while (!loader->read(loader, &nsf_file_ext, sizeof(nsf_file_ext)) + && !memcmp(nsf_file_ext.magic,id,4)) { + /* Got a NESM extension here. Checks for known extension type : + * right now, the only extension is "TIME" which give songs length. + * in frames. + */ + int size; + size = 0 + + nsf_file_ext.size[0] + + (nsf_file_ext.size[1] << 8) + + (nsf_file_ext.size[2] << 16) + + (nsf_file_ext.size[3] << 24); + + if (size < sizeof(nsf_file_ext)) { + log_printf("nsf : [%s] corrupt extension size (%d)\n", + loader->fname, size); + /* Not a fatal error here. Just skip extension loading. */ + break; + } + size -= sizeof(nsf_file_ext); + + if (!temp_nsf->song_frames + && !memcmp(nsf_file_ext.type,"TIME", 4) + && !(size & 3) + && (size >= 2*4) + && (size <= 256*4)) { + + uint8 tmp_time[256][4]; + int tsongs = size >> 2; + int i; + int songs = temp_nsf->num_songs; + + /* Add 1 for 0 which contains total time for all songs. */ + ++songs; + + if (loader->read(loader, tmp_time, size)) { + log_printf("nsf : [%s] missing extension data\n", + loader->fname); + /* Not a fatal error here. Just skip extension loading. */ + break; + } + /* Alloc song_frames for songs (not tsongs). */ + temp_nsf->song_frames = malloc(sizeof(*temp_nsf->song_frames) * songs); + if (!temp_nsf->song_frames) { + log_printf("nsf : [%s] extension alloc failed\n", + loader->fname); + /* Not a fatal error here. Just skip extension loading. */ + break; + } + + if (tsongs > songs) { + tsongs = songs; + } + + /* Copy time info. */ + for (i=0; i<tsongs; ++i) { + temp_nsf->song_frames[i] = 0 + | tmp_time[i][0] + | (tmp_time[i][1] << 8) + | (tmp_time[i][2] << 16) + | (tmp_time[i][2] << 24); + } + /* Clear missing (safety net). */ + for (; i<songs; ++i) { + temp_nsf->song_frames[i] = 0; + } + } else if (loader->skip(loader, size)) { + log_printf("nsf : [%s] extension skip failed\n", + loader->fname); + /* Not a fatal error here. Just skip extension loading. */ + break; + } + } + + + /* Close "file" */ + loader->close(loader); + loader = 0; /* Set up some variables */ nsf_setup(temp_nsf); - temp_nsf->apu = NULL; /* just make sure */ - if (nsf_cpuinit(temp_nsf)) - { - nsf_free(&temp_nsf); - return NULL; + if (nsf_cpuinit(temp_nsf)) { + log_printf("nsf : error cpu init\n"); + goto error; } - return temp_nsf; -} - -/* Free an NSF */ -void nsf_free(nsf_t **nsf) -{ - if (*nsf) - { - if ((*nsf)->apu) - apu_destroy((*nsf)->apu); - - nes_shutdown(*nsf); - if ((*nsf)->data) - free((*nsf)->data); - - free(*nsf); + /* $$$ ben : some people tell that goto are not clean. I am not agree with + * them. In most case, it allow to avoid code duplications, which are as + * most people know a source of error... Here we are sure of being clean + */ + error: + if (loader) { + loader->close(loader); + } + if (temp_nsf) { + nsf_free(&temp_nsf); } + return 0; } -void nsf_setchan(nsf_t *nsf, int chan, boolean enabled) +/* Load a ROM image into memory */ +nsf_t *nsf_load(const char *filename, void *source, int length) { - if (nsf) - { - nsf_setcontext(nsf); - apu_setchan(chan, enabled); - } + struct nsf_loader_t * loader = 0; + + /* $$$ ben : new loader */ + if (filename) { + nsf_file_loader.fname = (char *)filename; + loader = &nsf_file_loader.loader; + } else { + nsf_mem_loader.data = source; + nsf_mem_loader.len = length; + nsf_mem_loader.fname[0] = 0; + loader = &nsf_mem_loader.loader; + } + return nsf_load_extended(loader); } -void nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits, boolean stereo) +/* Free an NSF */ +void nsf_free(nsf_t **pnsf) { - ASSERT(nsf); + nsf_t *nsf; - /* make this NSF the current context */ - nsf_setcontext(nsf); + if (!pnsf) { + return; + } - /* create the APU */ - if (nsf->apu) + nsf = *pnsf; + /* $$$ ben : Don't see why passing a pointer to pointer + * is not to clear it :) */ + *pnsf = 0; + + if (nsf) { + if (nsf->apu) apu_destroy(nsf->apu); - nsf->apu = apu_create(sample_rate, nsf->playback_rate, sample_bits, stereo); - if (NULL == nsf->apu) - { - nsf_free(&nsf); - return; - } + nes_shutdown(nsf); + + if (nsf->data) + free(nsf->data); - apu_setext(nsf->apu, nsf_getext(nsf)); + if (nsf->song_frames) + free (nsf->song_frames); - /* go ahead and init all the read/write handlers */ - build_address_handlers(nsf); + free(nsf); + } +} - /* convenience? */ - nsf->process = nsf->apu->process; +int nsf_setchan(nsf_t *nsf, int chan, boolean enabled) +{ + if (!nsf) + return -1; - nes6502_setcontext(nsf->cpu); + nsf_setcontext(nsf); + return apu_setchan(chan, enabled); +} - if (track > nsf->num_songs) - track = nsf->num_songs; - else if (track < 1) - track = 1; +int nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits, + boolean stereo) +{ + if (!nsf) { + return -1; + } + + /* make this NSF the current context */ + nsf_setcontext(nsf); + + /* create the APU */ + if (nsf->apu) { + apu_destroy(nsf->apu); + } + + nsf->apu = apu_create(sample_rate, nsf->playback_rate, sample_bits, stereo); + if (NULL == nsf->apu) + { + /* $$$ ben : from my point of view this is not clean. Function should + * never destroy object it has not created... + */ + /* nsf_free(&nsf); */ + return -1; + } - nsf->current_song = track; + apu_setext(nsf->apu, nsf_getext(nsf)); + + /* go ahead and init all the read/write handlers */ + build_address_handlers(nsf); + + /* convenience? */ + nsf->process = nsf->apu->process; + + nes6502_setcontext(nsf->cpu); + + if (track > nsf->num_songs) + track = nsf->num_songs; + else if (track < 1) + track = 1; + + nsf->current_song = track; - apu_reset(); + apu_reset(); + + nsf_inittune(nsf); - nsf_inittune(nsf); + return nsf->current_song; } -void nsf_setfilter(nsf_t *nsf, int filter_type) +int nsf_setfilter(nsf_t *nsf, int filter_type) { - if (nsf) - { - nsf_setcontext(nsf); - apu_setfilter(filter_type); - } + if (!nsf) { + return -1; + } + nsf_setcontext(nsf); + return apu_setfilter(filter_type); } /* ** $Log: nsf.c,v $ -** Revision 1.4 2006/09/26 00:52:17 dgp85 -** Free the filename string and close the file pointer when returning. -** -** Found by Coverity Scan. -** -** Revision 1.3 2003/08/25 21:51:43 f1rmb -** Reduce GCC verbosity (various prototype declaration fixes). ffmpeg, wine and fft*post are untouched (fft: for now). +** Revision 1.3 2003/05/01 22:34:20 benjihan +** New NSF plugin ** -** Revision 1.2 2003/01/09 18:36:40 jkeil -** memcpy copies too much, corrupts malloc heap +** Revision 1.2 2003/04/09 14:50:32 ben +** Clean NSF api. ** -** Revision 1.1 2003/01/08 07:04:35 tmmm -** initial import of Nosefart sources +** Revision 1.1 2003/04/08 20:53:00 ben +** Adding more files... ** ** Revision 1.14 2000/07/05 14:54:45 matt ** fix for naughty Crystalis rip diff --git a/contrib/nosefart/nsf.h b/contrib/nosefart/nsf.h index 79ec1dbb6..79ce55c35 100644 --- a/contrib/nosefart/nsf.h +++ b/contrib/nosefart/nsf.h @@ -62,28 +62,29 @@ enum { NSF_FILTER_NONE, NSF_FILTER_LOWPASS, - NSF_FILTER_WEIGHTED + NSF_FILTER_WEIGHTED, + NSF_FILTER_MAX, /* $$$ ben : add this one for range chacking */ }; typedef struct nsf_s { /* NESM header */ - uint8 id[5]; /* NESM\x1A */ - uint8 version; /* spec version */ - uint8 num_songs; /* total num songs */ - uint8 start_song; /* first song */ - uint16 load_addr; /* loc to load code */ - uint16 init_addr; /* init call address */ - uint16 play_addr; /* play call address */ - uint8 song_name[32]; /* name of song */ - uint8 artist_name[32]; /* artist name */ - uint8 copyright[32]; /* copyright info */ - uint16 ntsc_speed; /* playback speed (if NTSC) */ - uint8 bankswitch_info[8]; /* initial code banking */ - uint16 pal_speed; /* playback speed (if PAL) */ - uint8 pal_ntsc_bits; /* NTSC/PAL determination bits */ - uint8 ext_sound_type; /* type of external sound gen. */ - uint8 reserved[4]; /* reserved */ + uint8 id[5]; /* NESM\x1A */ + uint8 version; /* spec version */ + uint8 num_songs; /* total num songs */ + uint8 start_song; /* first song */ + uint16 load_addr; /* loc to load code */ + uint16 init_addr; /* init call address */ + uint16 play_addr; /* play call address */ + uint8 song_name[32]; /* name of song */ + uint8 artist_name[32]; /* artist name */ + uint8 copyright[32]; /* copyright info */ + uint16 ntsc_speed; /* playback speed (if NTSC) */ + uint8 bankswitch_info[8]; /* initial code banking */ + uint16 pal_speed; /* playback speed (if PAL) */ + uint8 pal_ntsc_bits; /* NTSC/PAL determination bits */ + uint8 ext_sound_type; /* type of external sound gen. */ + uint8 reserved[4]; /* reserved */ /* things that the NSF player needs */ uint8 *data; /* actual NSF data */ @@ -92,6 +93,14 @@ typedef struct nsf_s uint8 current_song; /* current song */ boolean bankswitched; /* is bankswitched? */ + /* $$$ ben : Playing time ... */ + uint32 cur_frame; + uint32 cur_frame_end; + uint32 * song_frames; + + /* $$$ ben : Last error string */ + const char * errstr; + /* CPU and APU contexts */ nes6502_context *cpu; apu_t *apu; @@ -100,30 +109,55 @@ typedef struct nsf_s void (*process)(void *buffer, int num_samples); } XINE_PACKED nsf_t; +/* $$$ ben : Generic loader struct */ +struct nsf_loader_t { + /* Init and open. */ + int (*open)(struct nsf_loader_t * loader); + + /* Close and shutdown. */ + void (*close) (struct nsf_loader_t * loader); + + /* This function should return <0 on error, else the number of byte NOT read. + * that way a simple 0 test tell us if read was complete. + */ + int (*read) (struct nsf_loader_t * loader, void *data, int n); + + /* Get file length. */ + int (*length) (struct nsf_loader_t * loader); + + /* Skip n bytes. */ + int (*skip) (struct nsf_loader_t * loader,int n); + + /* Get filename (for debug). */ + const char * (*fname) (struct nsf_loader_t * loader); + +}; + /* Function prototypes */ -extern void nsf_init(void); +extern int nsf_init(void); -extern nsf_t *nsf_load(char *filename, void *source, int length); +extern nsf_t * nsf_load_extended(struct nsf_loader_t * loader); +extern nsf_t *nsf_load(const char *filename, void *source, int length); extern void nsf_free(nsf_t **nsf_info); -extern void nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits, - boolean stereo); +extern int nsf_playtrack(nsf_t *nsf, int track, int sample_rate, + int sample_bits, boolean stereo); extern void nsf_frame(nsf_t *nsf); -extern void nsf_setchan(nsf_t *nsf, int chan, boolean enabled); -extern void nsf_setfilter(nsf_t *nsf, int filter_type); +extern int nsf_setchan(nsf_t *nsf, int chan, boolean enabled); +extern int nsf_setfilter(nsf_t *nsf, int filter_type); #endif /* _NSF_H_ */ /* ** $Log: nsf.h,v $ -** Revision 1.3 2007/01/18 21:34:10 dgp85 -** __attribute__(packed) is used on the struct, not on its members. +** Revision 1.3 2003/05/01 22:34:20 benjihan +** New NSF plugin ** -** Revision 1.2 2003/12/05 15:55:01 f1rmb -** cleanup phase II. use xprintf when it's relevant, use xine_xmalloc when it's relevant too. Small other little fix (can't remember). Change few internal function prototype because it xine_t pointer need to be used if some xine's internal sections. NOTE: libdvd{nav,read} is still too noisy, i will take a look to made it quit, without invasive changes. To be continued... +** Revision 1.2 2003/04/09 14:50:32 ben +** Clean NSF api. ** -** Revision 1.1 2003/01/08 07:04:35 tmmm -** initial import of Nosefart sources +** Revision 1.1 2003/04/08 20:53:00 ben +** Adding more files... ** ** Revision 1.11 2000/07/04 04:59:24 matt ** removed DOS-specific stuff diff --git a/contrib/nosefart/types.h b/contrib/nosefart/types.h index 01f196035..c0293066c 100644 --- a/contrib/nosefart/types.h +++ b/contrib/nosefart/types.h @@ -31,10 +31,9 @@ #endif /* Define this if running on little-endian (x86) systems */ -#ifdef WORDS_BIGENDIAN -#undef HOST_LITTLE_ENDIAN -#else -#define HOST_LITTLE_ENDIAN + +#ifndef DCPLAYA +# define HOST_LITTLE_ENDIAN #endif #ifdef __GNUC__ @@ -46,13 +45,25 @@ #endif /* These should be changed depending on the platform */ -typedef char int8; -typedef short int16; -typedef int int32; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; + + +#ifdef __BEOS__ /* added by Eli Dayan (for compiling under BeOS) */ + + /* use types in the BeOS Support Kit instead */ + #include <be/support/SupportDefs.h> +#elif defined (DCPLAYA) /* $$$ added by ben (for compiling with dcplaya) */ +# include <arch/types.h> +#else + typedef char int8; + typedef short int16; + typedef int int32; + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + +#endif typedef uint8 boolean; diff --git a/contrib/nosefart/version.h b/contrib/nosefart/version.h index d7dcb2e5d..38d69c61c 100644 --- a/contrib/nosefart/version.h +++ b/contrib/nosefart/version.h @@ -20,7 +20,7 @@ ** version.h ** ** Program name / version definitions -** $Id: version.h,v 1.2 2003/12/05 15:55:01 f1rmb Exp $ +** $Id: version.h,v 1.1 2003/04/08 20:46:46 ben Exp $ */ #ifndef _VERSION_H_ @@ -32,17 +32,14 @@ #define APP_STRING "Nofrendo" #endif /* NSF_PLAYER */ -#define APP_VERSION "1.92" +#define APP_VERSION "2.3-mls" #endif /* _VERSION_H_ */ /* ** $Log: version.h,v $ -** Revision 1.2 2003/12/05 15:55:01 f1rmb -** cleanup phase II. use xprintf when it's relevant, use xine_xmalloc when it's relevant too. Small other little fix (can't remember). Change few internal function prototype because it xine_t pointer need to be used if some xine's internal sections. NOTE: libdvd{nav,read} is still too noisy, i will take a look to made it quit, without invasive changes. To be continued... -** -** Revision 1.1 2003/01/08 07:04:36 tmmm -** initial import of Nosefart sources +** Revision 1.1 2003/04/08 20:46:46 ben +** add new input for NES music file. ** ** Revision 1.7 2000/07/04 04:46:55 matt ** updated version number diff --git a/doc/README.MINGWCROSS b/doc/README.MINGWCROSS index d721ca941..9aefccfaa 100644 --- a/doc/README.MINGWCROSS +++ b/doc/README.MINGWCROSS @@ -8,10 +8,13 @@ In this case "native" means programs which don't require extra DLLs like cygwin DLL. Mingw32 programs use DLLs supplied with all current Win32 platforms. Thus the programs are light weight and easy to distribute. - This document describes by shell commands how to compile and install MinGW cross development tools on Unix host and how to use it for building windows -version of xine. +version of xine. See README.WIN32 how to use it to build xine. + +For creating 64bit version of Mingw32 toolchain, see +mingw/mingw-w64-doc/howto-build/mingw-w64-howto-build.txt in mingw32-w64 +sources. Download @@ -19,7 +22,8 @@ Download MinGW packages: - http://mingw.org/download.shtml + http://mingw.org, or + http://mingw-w64.sourceforge.net 1) binutils (sources), binutils-build.sh 2) gcc-core, gcc-c++ (sources), gcc-build.sh @@ -33,6 +37,7 @@ Download Pthread Win32: ftp://sources.redhat.com/pub/pthreads-win32/ + (plus 64bit external patches for mingw32-w64) zlib: @@ -54,7 +59,7 @@ In the following text are used symbols $PREFIX and $USER with this meaning: mkdir bin cd bin ../binutils-2.13.90-20030111-1-src/configure \ - --target=i386-mingw32 \ + --target=i686-pc-mingw32 \ --prefix=$PREFIX make su @@ -82,7 +87,7 @@ In the following text are used symbols $PREFIX and $USER with this meaning: # compile and install the compiler # # if you'll want rerun this step, I recommend delete - # $PREFIX/i386-mingw32/sys-include + # $PREFIX/i686-pc-mingw32/sys-include # tar xzf gcc-core-3.3.1-20030804-1-src.tar.gz tar xzf gcc-g++-3.3.1-20030804-1-src.tar.gz @@ -94,7 +99,7 @@ In the following text are used symbols $PREFIX and $USER with this meaning: # see gcc-3.3.1-1-build.sh ../gcc-3.3.1-20030804-1/configure \ --disable-shared \ - --target=i386-mingw32 \ + --target=i686-pc-mingw32 \ --with-headers=../runtime/include \ --with-libs=../runtime/lib \ --prefix=$PREFIX @@ -109,18 +114,18 @@ In the following text are used symbols $PREFIX and $USER with this meaning: 4. recompile w32api and mingw-runtime from sources (optional) # - # installing must be into $PREFIX/i386-mingw32 + # installing must be into $PREFIX/i686-pc-mingw32 # tar xzf w32api-2.5-src.tar.gz cd w32api-2.5 - ./configure --prefix=$PREFIX/i386-mingw32 --host=i386-mingw32 + ./configure --prefix=$PREFIX/i686-pc-mingw32 --host=i686-pc-mingw32 make su make install exit # - # installing must be into $PREFIX/i386-mingw32 + # installing must be into $PREFIX/i686-pc-mingw32 # tar xzf mingw-runtime-3.3-src.tar.gz cd mingw-runtime-3.3 @@ -128,12 +133,12 @@ In the following text are used symbols $PREFIX and $USER with this meaning: # package) ... # compiling - CC=i386-mingw32-gcc \ - DLLTOOL=i386-mingw32-dlltool \ - AR=i386-mingw32-ar \ - AS=i386-mingw32-as \ - RANLIB=i386-mingw32-ranlib \ - ./configure --prefix=$PREFIX/i386-mingw32 --target=i386-mingw32 + CC=i686-pc-mingw32-gcc \ + DLLTOOL=i686-pc-mingw32-dlltool \ + AR=i686-pc-mingw32-ar \ + AS=i686-pc-mingw32-as \ + RANLIB=i686-pc-mingw32-ranlib \ + ./configure --prefix=$PREFIX/i686-pc-mingw32 --target=i686-pc-mingw32 make su make install @@ -151,14 +156,14 @@ In the following text are used symbols $PREFIX and $USER with this meaning: 6. compile and install pthreads-win32 - tar xzf pthreads-w32-2-7-0-release.tar.gz - cd pthreads-w32-2-7-0-release/ - make CROSS=i386-mingw32- PTHREAD_DEF=pthreadGC2.def clean GC + tar xzf pthreads-w32-2-8-0-release.tar.gz + cd pthreads-w32-2-8-0-release/ + make CROSS=i686-pc-mingw32- clean GC # # possibility to use pthread library in M$ Visual C (optional) # mv pthread.def pthreadGC2.def - wine LIB.EXE /machine:i386 /def:pthreadGC2.def + wine LIB.EXE /machine:i686 /def:pthreadGC2.def # # installing # @@ -176,16 +181,9 @@ In the following text are used symbols $PREFIX and $USER with this meaning: 7. compile and install zlib - tar xjf zlib-1.2.3.tar.bz2 - cd zlib-1.2.3 - # - # small workaround in Makefile: - # - sed -e 's/dllwrap /i386-mingw32-dllwrap /g' win32/Makefile.gcc > Makefile - # - # compiling - # - make CC=i386-mingw32-gcc AR=i386-mingw32-ar RC=i386-mingw32-windres STATICLIB=libz-static.a IMPLIB=libz.a + tar xzf zlib-1.2.5.tar.gz + cd zlib-1.2.5 + make -f win32/Makefile.gcc PREFIX=i686-pc-mingw32- STATICLIB=libz-static.a IMPLIB=libz.a # # possibility to use zlib library in M$ Visual C (optional) # @@ -212,7 +210,7 @@ Now we can build xine library for Windows by this way: # (the build option is needed only for forcing cross compilation mode) # ./configure \ - --host=i386-mingw32 \ + --host=i686-pc-mingw32 \ --build=i686-debian-linux \ --disable-freetype \ --disable-vcd \ diff --git a/doc/README.WIN32 b/doc/README.WIN32 index 989728b07..a1dc461f5 100644 --- a/doc/README.WIN32 +++ b/doc/README.WIN32 @@ -44,8 +44,6 @@ How to build: # install and manually remove the static plugins # make install DESTDIR=/tmp/xine-lib - rm /tmp/xine-lib/bin/plugins/*.a - rm /tmp/xine-lib/bin/plugins/post/*.a Prepare xine library for using in M$ compilers too: # run terminal window (MinGW for example) @@ -56,6 +54,9 @@ Prepare xine library for using in M$ compilers too: <path_to_M$VC>/VC98/BIN/LIB.EXE /machine:i386 /def:libxine-1.def rm libxine-1.dll +For 64bit, use x86 instead of i386: + <path_to_M$VC>/VC98/BIN/LIB.EXE /machine:x86 /def:libxine-1.def + 2. CygWin port -------------- @@ -165,8 +166,8 @@ There remains many of work yet on Windows port. Limitations: - file > 1GB doesn't work (MinGW problem?) - - build system isn't fully tuned for cross-compiling - seeking doesn't work with testing frontend, but it should be OK in library + - libcdio not ported to mingw32-w64 (frelling headers :-)) Bugs: - random crashes and random locks in stress tests diff --git a/doc/faq/faq.docbook b/doc/faq/faq.docbook index 531f02b01..d26dc343a 100644 --- a/doc/faq/faq.docbook +++ b/doc/faq/faq.docbook @@ -305,7 +305,7 @@ You'll need an HG snapshot tarball or source checked out from the repository. </para> <para> - First, make sure that the "devscripts" package is installed. You'll + First, make sure that the "devscripts" and "build-essential" packages are installed. You'll then need the following commands (the first one isn't needed unless you're using a snapshot tarball): <screen> <command>tar xzf <PACKAGE-VER.tar.gz></command> diff --git a/lib/os_internal.h b/lib/os_internal.h index 8136ce76e..b06b51112 100644 --- a/lib/os_internal.h +++ b/lib/os_internal.h @@ -257,7 +257,11 @@ int xine_private_pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct ti # ifdef HAVE_SYS_STAT_H # include <sys/stat.h> # endif -# define mkdir(A, B) _mkdir((A)) +# ifdef __MINGW64__ +# define mkdir(A, B) mkdir((A)) +# else +# define mkdir(A, B) _mkdir((A)) +# endif # ifndef S_ISDIR # define S_ISDIR(m) ((m) & _S_IFDIR) diff --git a/m4/attributes.m4 b/m4/attributes.m4 index c7ef73e68..4f0442865 100644 --- a/m4/attributes.m4 +++ b/m4/attributes.m4 @@ -109,14 +109,21 @@ AC_DEFUN([CC_NOUNDEFINED], [ dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads dnl are requested, as different implementations are present; to avoid problems dnl use -Wl,-z,defs only for those platform not behaving this way. + dnl + dnl MinGW platforms: for libraries required -no-undefined, + dnl use it only for libraries in mingw32-w64 + *-freebsd* | *-openbsd*) ;; + *-mingw*) + LDFLAGS_NOUNDEFINED="-no-undefined" + ;; *) dnl First of all check for the --no-undefined variant of GNU ld. This allows dnl for a much more readable commandline, so that people can understand what dnl it does without going to look for what the heck -z defs does. for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) - break + if test "x$LDFLAGS_NOUNDEFINED" = "x"; then break; fi done ;; esac diff --git a/misc/libxine.pc.in b/misc/libxine.pc.in index 1b9afeac6..cf5bf854e 100644 --- a/misc/libxine.pc.in +++ b/misc/libxine.pc.in @@ -16,7 +16,7 @@ scriptdir=@XINE_SCRIPTPATH@ localedir=@XINE_LOCALEDIR@ objcflags=@OBJCFLAGS@ -xine_list=${bindir}/xine-list-@XINE_SERIES@ +xine_list=${bindir}/xine-list-@XINE_SERIES@@EXEEXT@ Name: libxine Description: The xine engine library diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index 2c0b7df4f..6392aaac0 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -304,8 +304,12 @@ static int parse_content_compression (demux_matroska_t *this, matroska_track_t * } break; case MATROSKA_ID_CE_COMPSETTINGS: - lprintf("ContentCompSettings (UNSUPPORTED)\n"); - if (!ebml_skip(ebml, &elem)) + lprintf("ContentCompSettings\n"); + track->compress_settings = calloc(1, elem.len); + track->compress_len = elem.len; + if (elem.len > this->compress_maxlen) + this->compress_maxlen = elem.len; + if(!ebml_read_binary(ebml, &elem, track->compress_settings)) return 0; break; default: @@ -1785,8 +1789,8 @@ static int find_track_by_id(demux_matroska_t *this, int track_num, } -static int read_block_data (demux_matroska_t *this, size_t len) { - alloc_block_data(this, len); +static int read_block_data (demux_matroska_t *this, size_t len, size_t offset) { + alloc_block_data(this, len + offset); /* block datas */ if (! this->block_data) { @@ -1794,7 +1798,7 @@ static int read_block_data (demux_matroska_t *this, size_t len) { "demux_matroska: memory allocation error\n"); return 0; } - if (this->input->read(this->input, this->block_data, len) != len) { + if (this->input->read(this->input, this->block_data + offset, len) != len) { off_t pos = this->input->get_current_pos(this->input); xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_matroska: read error at position %" PRIdMAX "\n", @@ -1824,8 +1828,9 @@ static int parse_block (demux_matroska_t *this, size_t block_size, int16_t timecode_diff; int64_t pts, xduration; int decoder_flags = 0; + size_t headers_len = 0; - data = this->block_data; + data = this->block_data + this->compress_maxlen; if (!(num_len = parse_ebml_uint(this, data, &track_num))) return 0; data += num_len; @@ -1878,12 +1883,21 @@ static int parse_block (demux_matroska_t *this, size_t block_size, decoder_flags |= BUF_FLAG_PREVIEW; } + if (track->compress_algo == MATROSKA_COMPRESS_HEADER_STRIP) + headers_len = track->compress_len; + if (lacing == MATROSKA_NO_LACING) { size_t block_size_left; lprintf("no lacing\n"); - block_size_left = (this->block_data + block_size) - data; - lprintf("size: %d, block_size: %u\n", block_size_left, block_size); + block_size_left = (this->block_data + block_size + this->compress_maxlen) - data; + lprintf("size: %d, block_size: %u, block_offset: %u\n", block_size_left, block_size, this->compress_maxlen); + + if (headers_len) { + data -= headers_len; + xine_fast_memcpy(data, track->compress_settings, headers_len); + block_size_left += headers_len; + } if (track->handle_content != NULL) { track->handle_content((demux_plugin_t *)this, track, @@ -1913,7 +1927,7 @@ static int parse_block (demux_matroska_t *this, size_t block_size, "demux_matroska: too many frames: %d\n", lace_num); return 0; } - block_size_left = this->block_data + block_size - data; + block_size_left = this->block_data + block_size + this->compress_maxlen - data; switch (lacing) { case MATROSKA_XIPH_LACING: { @@ -2046,7 +2060,7 @@ static int parse_simpleblock(demux_matroska_t *this, size_t block_len, uint64_t if( file_len ) normpos = (int) ( (double) block_pos * 65535 / file_len ); - if (!read_block_data(this, block_len)) + if (!read_block_data(this, block_len, this->compress_maxlen)) return 0; has_block = 1; @@ -2085,7 +2099,7 @@ static int parse_block_group(demux_matroska_t *this, if( file_len ) normpos = (int) ( (double) block_pos * 65535 / file_len ); - if (!read_block_data(this, elem.len)) + if (!read_block_data(this, elem.len, this->compress_maxlen)) return 0; has_block = 1; diff --git a/src/demuxers/demux_matroska.h b/src/demuxers/demux_matroska.h index fe1b7f6cf..670827598 100644 --- a/src/demuxers/demux_matroska.h +++ b/src/demuxers/demux_matroska.h @@ -96,6 +96,7 @@ typedef struct { int num_sub_tracks; matroska_track_t *tracks[MAX_STREAMS]; + size_t compress_maxlen; /* maintain editions, number and capacity */ int num_editions, cap_editions; diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index c944e3c9e..c342cc381 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -457,7 +457,7 @@ static inline void dump_moov_atom(unsigned char *moov_atom, int moov_atom_size) FILE *f; - f = fopen(RAW_MOOV_FILENAME, "w"); + f = fopen(RAW_MOOV_FILENAME, "wb"); if (!f) { perror(RAW_MOOV_FILENAME); return; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index b038e52ef..49880f9a2 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -2344,6 +2344,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, demux_ts_t *this; int i; int hdmv = -1; + int size; switch (stream->content_detection_method) { @@ -2352,12 +2353,13 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, int i, j; int try_again, ts_detected; - if (!_x_demux_read_header(input, buf, sizeof(buf))) + size = _x_demux_read_header(input, buf, sizeof(buf)); + if (size < PKT_SIZE) return NULL; if (detect_ts(buf, sizeof(buf), PKT_SIZE)) hdmv = 0; - else if (detect_ts(buf, sizeof(buf), PKT_SIZE+4)) + else if (size >= PKT_SIZE + 4 && detect_ts(buf, sizeof(buf), PKT_SIZE+4)) hdmv = 1; else return NULL; diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 23e115edc..2fad31ce4 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -272,6 +272,8 @@ struct matroska_track_s { uint32_t codec_private_len; int default_flag; uint32_t compress_algo; + uint32_t compress_len; + char *compress_settings; uint32_t buf_type; fifo_buffer_t *fifo; diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index 31bc51bc2..05250f51c 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -1280,7 +1280,7 @@ static void _cdda_mkdir_safe(xine_t *xine, char *path) { hList = FindFirstFile(szDir, &FileData); if (hList == INVALID_HANDLE_VALUE) { - if(_mkdir(path) != 0) { + if(mkdir(path, 0) != 0) { xprintf(xine, XINE_VERBOSITY_DEBUG, "input_cdda: mkdir(%s) failed.\n", path); return; } diff --git a/src/input/vcd/xineplug_inp_vcd.c b/src/input/vcd/xineplug_inp_vcd.c index acd4775f4..1f6a885db 100644 --- a/src/input/vcd/xineplug_inp_vcd.c +++ b/src/input/vcd/xineplug_inp_vcd.c @@ -1500,6 +1500,10 @@ vcd_class_dispose (input_class_t *this_gen) { dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); vcd_close(class); + free(class->vcd_device); + free(my_vcd.v_config.title_format); + free(my_vcd.v_config.comment_format); + free(class); } /* Update the xine player title text. */ diff --git a/src/libreal/xine_real_video_decoder.c b/src/libreal/xine_real_video_decoder.c index a4c40668b..ce717fe81 100644 --- a/src/libreal/xine_real_video_decoder.c +++ b/src/libreal/xine_real_video_decoder.c @@ -380,7 +380,7 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) xine_hexdump (this->chunk_buffer, this->chunk_buffer_size); printf ("libreal: transform_in:\n"); - xine_hexdump ((uint8_t *) &transform_in, sizeof(rv_xform_in_t)); + xine_hexdump ((uint8_t *) &transform_in, sizeof(transform_in_t)); printf ("libreal: chunk_table:\n"); xine_hexdump ((uint8_t *) buf->decoder_info_ptr[2], diff --git a/src/post/planar/noise.c b/src/post/planar/noise.c index 015925138..471670fb9 100644 --- a/src/post/planar/noise.c +++ b/src/post/planar/noise.c @@ -39,8 +39,10 @@ #ifdef ARCH_X86_64 # define REG_a "rax" +# define intarch_t int64_t #else # define REG_a "eax" +# define intarch_t int32_t #endif #define MAX_NOISE 4096 @@ -155,7 +157,7 @@ static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int le #ifdef ARCH_X86 static inline void lineNoise_MMX(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){ - long mmx_len= len&(~7); + intarch_t mmx_len= len&(~7); noise+=shift; asm volatile( @@ -182,7 +184,7 @@ static inline void lineNoise_MMX(uint8_t *dst, uint8_t *src, int8_t *noise, int //duplicate of previous except movntq static inline void lineNoise_MMX2(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){ - long mmx_len= len&(~7); + intarch_t mmx_len= len&(~7); noise+=shift; asm volatile( @@ -225,7 +227,7 @@ static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t ** #ifdef ARCH_X86 static inline void lineNoiseAvg_MMX(uint8_t *dst, uint8_t *src, int len, int8_t **shift){ - long mmx_len= len&(~7); + intarch_t mmx_len= len&(~7); asm volatile( "mov %5, %%"REG_a" \n\t" diff --git a/src/spu_dec/sputext_demuxer.c b/src/spu_dec/sputext_demuxer.c index 0b89d03c8..a8e252c30 100644 --- a/src/spu_dec/sputext_demuxer.c +++ b/src/spu_dec/sputext_demuxer.c @@ -1374,7 +1374,8 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ (strncasecmp(ending, ".sub", 4) != 0) && (strncasecmp(ending, ".srt", 4) != 0) && (strncasecmp(ending, ".smi", 4) != 0) && - (strncasecmp(ending, ".ssa", 4) != 0))) { + (strncasecmp(ending, ".ssa", 4) != 0) && + (strncasecmp(ending, ".ass", 4) != 0))) { free (this); return NULL; } @@ -1431,7 +1432,7 @@ void *init_sputext_demux_class (xine_t *xine, void *data) { /* do not report this mimetype, it might confuse browsers. */ /* "text/plain: asc txt sub srt: VIDEO subtitles;" */ this->demux_class.mimetypes = NULL; - this->demux_class.extensions = "asc txt sub srt smi ssa"; + this->demux_class.extensions = "asc txt sub srt smi ssa ass"; this->demux_class.dispose = default_demux_class_dispose; /* diff --git a/src/video_dec/image.c b/src/video_dec/image.c index a4b6e43bd..cbbb9d722 100644 --- a/src/video_dec/image.c +++ b/src/video_dec/image.c @@ -101,12 +101,14 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { /* * this->image -> rgb data */ + InitializeMagick(NULL); wand = NewMagickWand(); status = MagickReadImageBlob(wand, this->image, this->index); this->index = 0; if (!status) { DestroyMagickWand(wand); + DestroyMagick(); lprintf("error loading image\n"); return; } @@ -116,6 +118,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { img_buf = malloc(width * height * 3); MagickGetImagePixels(wand, 0, 0, width, height, "RGB", CharPixel, img_buf); DestroyMagickWand(wand); + DestroyMagick(); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height); diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index 26f1c1178..f37c730b8 100644 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -110,6 +110,12 @@ typedef struct { * * ----------------------------------------- */ +typedef enum { + VO_DIRECTX_HWACCEL_FULL = 0, + VO_DIRECTX_HWACCEL_SCALE = 1, + VO_DIRECTX_HWACCEL_NONE = 2 +} vo_directx_hwaccel_enum; + typedef struct { vo_driver_t vo_driver; win32_visual_t *win32_visual; @@ -128,6 +134,7 @@ typedef struct { uint32_t width; /* frame with */ uint32_t height; /* frame height */ double ratio; /* frame ratio */ + vo_directx_hwaccel_enum hwaccel; /* requested level of HW acceleration */ yuv2rgb_factory_t *yuv2rgb_factory; /* used for format conversion */ yuv2rgb_t *yuv2rgb; /* used for format conversion */ @@ -144,6 +151,8 @@ typedef struct { xine_t *xine; } directx_class_t; +char *config_hwaccel_values[] = {"full", "scale", "none", NULL }; + /* ----------------------------------------- * * BEGIN : Direct Draw and win32 handlers @@ -322,6 +331,8 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he ddsd.dwWidth = width; ddsd.dwHeight = height; + if (win32_driver->hwaccel <= VO_DIRECTX_HWACCEL_FULL) { + if( format == XINE_IMGFMT_YV12 ) { /* the requested format is XINE_IMGFMT_YV12 */ @@ -378,6 +389,10 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK ) return TRUE; + } + + if (win32_driver->hwaccel <= VO_DIRECTX_HWACCEL_SCALE) { + /* Our fallback method is to create a back buffer * with the same image format as the primary surface */ @@ -392,10 +407,13 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK ) return TRUE; + } + /* Our second fallback - all w/o HW acceleration */ lprintf("CreateSecondary() - Falling back, disabling HW acceleration \n"); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + win32_driver->act_format = IMGFMT_NATIVE; if( (result = IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 )) == DD_OK ) return TRUE; @@ -625,7 +643,7 @@ static boolean Overlay( LPDIRECTDRAWSURFACE src_surface, RECT * src_rect, } else { - Error( 0, "IDirectDrawSurface_UpdateOverlay : error 0x%lx", result ); + Error( 0, "IDirectDrawSurface_UpdateOverlay : error 0x%lx. You can try disable hardware acceleration (option video.directx.hwaccel).", result ); return FALSE; } } @@ -1265,6 +1283,15 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *wi win32_driver->vo_driver.dispose = win32_exit; win32_driver->vo_driver.redraw_needed = win32_redraw_needed; + win32_driver->hwaccel = class->config->register_enum(class->config, + "video.directx.hwaccel", 0, config_hwaccel_values, + _("HW acceleration level"), + _("Possible values (default full):\n\n" +"full: full acceleration\n" +"scale: disable colorspace conversion (HW scaling only)\n" +"none: disable all acceleration"), + 10, NULL, NULL); + if (!CreatePrimary( win32_driver )) { Destroy( win32_driver ); return NULL; diff --git a/src/xine-engine/Makefile.am b/src/xine-engine/Makefile.am index 64ba68a97..15553380a 100644 --- a/src/xine-engine/Makefile.am +++ b/src/xine-engine/Makefile.am @@ -12,7 +12,7 @@ EXTRA_DIST = lrb.c lrb.h accel_vdpau.h accel_xvmc.h if WIN32 DEF_FILE = libxine-$(XINE_MAJOR).def -def_ldflags="-Wl,--output-def,$(DEF_FILE)" +def_ldflags=-Wl,--output-def,$(DEF_FILE) $(LDFLAGS_NOUNDEFINED) else DEF_FILE = endif diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index e5c42f6ea..b82db8b77 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -1026,8 +1026,8 @@ void xine_config_save (xine_t *xine, const char *filename) { lprintf("backing up configfile to %s\n", temp); - f_backup = fopen(temp, "w"); - f_config = fopen(filename, "r"); + f_backup = fopen(temp, "wb"); + f_config = fopen(filename, "rb"); if (f_config && f_backup && (stat(filename, &config_stat) == 0)) { char *buf = NULL; diff --git a/src/xine-engine/events.c b/src/xine-engine/events.c index 33d9988be..11d6e8bd7 100644 --- a/src/xine-engine/events.c +++ b/src/xine-engine/events.c @@ -193,6 +193,7 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) { while ( (event = xine_event_get (queue)) ) { xine_event_free (event); } + xine_list_delete(queue->events); pthread_mutex_destroy(&queue->lock); pthread_cond_destroy(&queue->new_event); diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 93fc2173d..85f43b357 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -241,9 +241,6 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con xprintf(stream->xine, XINE_VERBOSITY_LOG, _("info_helper: unsupported conversion %s -> UTF-8, no conversion performed\n"), enc); - if (system_enc) - free(system_enc); - if (cd != (iconv_t)-1) { char *utf8_value; ICONV_CONST char *inbuf; @@ -273,6 +270,8 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con return; } } + + free(system_enc); } #endif diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index c2e6641ec..a03ac5686 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -696,6 +696,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init (&stream->frontend_lock, &attr); + pthread_mutexattr_destroy(&attr); /* * Clear meta/stream info @@ -1534,6 +1535,8 @@ static void xine_dispose_internal (xine_stream_t *stream) { stream->metronom->exit (stream->metronom); + xine_list_delete(stream->event_queues); + pthread_mutex_lock(&stream->xine->streams_lock); ite = xine_list_find(stream->xine->streams, stream); if (ite) { @@ -1578,7 +1581,6 @@ void xine_dispose (xine_stream_t *stream) { if (stream->osd_renderer) stream->osd_renderer->close( stream->osd_renderer ); - _x_refcounter_dec(stream->refcounter); } @@ -1607,6 +1609,8 @@ void xine_exit (xine_t *this) { if(this->port_ticket) this->port_ticket->dispose(this->port_ticket); + pthread_mutex_destroy(&this->log_lock); + #if defined(WIN32) WSACleanup(); #endif @@ -1652,6 +1656,7 @@ xine_t *xine_new (void) { * log buffers */ memset(this->log_buffers, 0, sizeof(this->log_buffers)); + pthread_mutex_init (&this->log_lock, NULL); #ifdef WIN32 @@ -1747,7 +1752,6 @@ void xine_init (xine_t *this) { * locks */ pthread_mutex_init (&this->streams_lock, NULL); - pthread_mutex_init (&this->log_lock, NULL); /* initialize color conversion tables and functions */ init_yuv_conversion(); diff --git a/src/xine-utils/mangle.h b/src/xine-utils/mangle.h index 4ca7db7a5..a897e9229 100644 --- a/src/xine-utils/mangle.h +++ b/src/xine-utils/mangle.h @@ -36,10 +36,15 @@ // Use rip-relative addressing if compiling PIC code on x86-64. #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__DJGPP__) || \ defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# if defined(__MINGW64__) +# define EXTERN_PREFIX "" +# else +# define EXTERN_PREFIX "_" +# endif # if defined(__x86_64__) && defined(__PIC__) -# define MANGLE(a) "_" #a"(%%rip)" +# define MANGLE(a) EXTERN_PREFIX #a"(%%rip)" # else -# define MANGLE(a) "_" #a +# define MANGLE(a) EXTERN_PREFIX #a # endif #else # if defined(__x86_64__) && defined(__PIC__) diff --git a/src/xine-utils/memcpy.c b/src/xine-utils/memcpy.c index b7611ed86..cea2b5b0b 100644 --- a/src/xine-utils/memcpy.c +++ b/src/xine-utils/memcpy.c @@ -39,6 +39,8 @@ #ifdef HAVE_SYS_TIMES_H #include <sys/times.h> +#else +#include <time.h> #endif #include <stdlib.h> @@ -124,7 +126,7 @@ quote of the day: /* for small memory blocks (<256 bytes) this version is faster */ #define small_memcpy(to,from,n)\ {\ -register unsigned long int dummy;\ +register uintptr_t dummy;\ __asm__ __volatile__(\ "rep; movsb"\ :"=&D"(to), "=&S"(from), "=&c"(dummy)\ @@ -154,7 +156,7 @@ int d0, d1, d2; "movsb\n" "2:" : "=&c" (d0), "=&D" (d1), "=&S" (d2) - :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + :"0" (n/4), "q" (n),"1" ((uintptr_t) to),"2" ((uintptr_t) from) : "memory"); return (to); @@ -191,9 +193,9 @@ static void * sse_memcpy(void * to, const void * from, size_t len) if(len >= MIN_LEN) { - register unsigned long int delta; + register uintptr_t delta; /* Align destinition to MMREG_SIZE -boundary */ - delta = ((unsigned long int)to)&(SSE_MMREG_SIZE-1); + delta = ((uintptr_t)to)&(SSE_MMREG_SIZE-1); if(delta) { delta=SSE_MMREG_SIZE-delta; @@ -202,7 +204,7 @@ static void * sse_memcpy(void * to, const void * from, size_t len) } i = len >> 6; /* len/64 */ len&=63; - if(((unsigned long)from) & 15) + if(((uintptr_t)from) & 15) /* if SRC is misaligned */ for(; i>0; i--) { @@ -263,9 +265,9 @@ static void * mmx_memcpy(void * to, const void * from, size_t len) if(len >= MMX1_MIN_LEN) { - register unsigned long int delta; + register uintptr_t delta; /* Align destinition to MMREG_SIZE -boundary */ - delta = ((unsigned long int)to)&(MMX_MMREG_SIZE-1); + delta = ((uintptr_t)to)&(MMX_MMREG_SIZE-1); if(delta) { delta=MMX_MMREG_SIZE-delta; @@ -328,9 +330,9 @@ static void * mmx2_memcpy(void * to, const void * from, size_t len) if(len >= MIN_LEN) { - register unsigned long int delta; + register uintptr_t delta; /* Align destinition to MMREG_SIZE -boundary */ - delta = ((unsigned long int)to)&(MMX_MMREG_SIZE-1); + delta = ((uintptr_t)to)&(MMX_MMREG_SIZE-1); if(delta) { delta=MMX_MMREG_SIZE-delta; @@ -428,7 +430,7 @@ static uint64_t rdtsc(int config_flags) struct tms tp; return times(&tp); #else - return ((uint64_t)0); + return clock(); #endif /* HAVE_SYS_TIMES_H */ } #endif diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c index 320733ebf..ba0c51994 100644 --- a/src/xine-utils/xmlparser.c +++ b/src/xine-utils/xmlparser.c @@ -143,7 +143,7 @@ static void xml_parser_free_props(xml_property_t *current_property) { } static void xml_parser_free_tree_rec(xml_node_t *current_node, int free_next) { - lprintf("xml_parser_free_tree_rec: %s\n", current_node->name); + lprintf("xml_parser_free_tree_rec: %s\n", current_node ? current_node->name : NULL); if (current_node) { /* properties */ |