diff options
author | Andreas Henriksson <andreas@fatal.set> | 2008-03-25 15:56:13 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-03-25 15:56:13 +0000 |
commit | a4d0dacec222cbeb9853b56f4900f5881d67b99b (patch) | |
tree | 953651f2ca39872d58fc2d0212cd9b2919088850 /gst/nsf/nes6502.c | |
parent | 09ec92549f052d8cb8c157107ccd1359e6f2da1b (diff) | |
download | gst-plugins-bad-a4d0dacec222cbeb9853b56f4900f5881d67b99b.tar.gz gst-plugins-bad-a4d0dacec222cbeb9853b56f4900f5881d67b99b.tar.bz2 gst-plugins-bad-a4d0dacec222cbeb9853b56f4900f5881d67b99b.zip |
gst/nsf/: Update our internal nosefart to nosefart-2.7-mls to fix segfaults on some files. Fixes bug #498237.
Original commit message from CVS:
Patch by: Andreas Henriksson <andreas at fatal dot set>
* gst/nsf/Makefile.am:
* gst/nsf/dis6502.h:
* gst/nsf/fds_snd.c:
* gst/nsf/fds_snd.h:
* gst/nsf/fmopl.c:
* gst/nsf/fmopl.h:
* gst/nsf/gstnsf.c:
* gst/nsf/log.c:
* gst/nsf/log.h:
* gst/nsf/memguard.c:
* gst/nsf/memguard.h:
* gst/nsf/mmc5_snd.c:
* gst/nsf/mmc5_snd.h:
* gst/nsf/nes6502.c:
* gst/nsf/nes6502.h:
* gst/nsf/nes_apu.c:
* gst/nsf/nes_apu.h:
* gst/nsf/nsf.c:
* gst/nsf/nsf.h:
* gst/nsf/osd.h:
* gst/nsf/types.h:
* gst/nsf/vrc7_snd.c:
* gst/nsf/vrc7_snd.h:
* gst/nsf/vrcvisnd.c:
* gst/nsf/vrcvisnd.h:
Update our internal nosefart to nosefart-2.7-mls to fix segfaults
on some files. Fixes bug #498237.
Remove some // comments, fix some compiler warnings and use pow()
instead of a slow, selfmade implementation.
Diffstat (limited to 'gst/nsf/nes6502.c')
-rw-r--r-- | gst/nsf/nes6502.c | 250 |
1 files changed, 204 insertions, 46 deletions
diff --git a/gst/nsf/nes6502.c b/gst/nsf/nes6502.c index 28bdc432..e2ed01f7 100644 --- a/gst/nsf/nes6502.c +++ b/gst/nsf/nes6502.c @@ -944,7 +944,7 @@ ADD_CYCLES(cycles); \ } -#define NSF_SEC() \ +#define SEC() \ { \ SET_FLAG(C_FLAG); \ ADD_CYCLES(2); \ @@ -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,82 +1175,209 @@ 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 */ + +#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) +_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) { -#ifdef HOST_LITTLE_ENDIAN + 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)); -#else -#ifdef TARGET_CPU_PPC +#elif defined(TARGET_CPU_PPC) return __lhbrx (ram, address); #else - uint32 x = (uint32) * (uint16 *) (ram + address); - - return (x << 8) | (x >> 8); -#endif /* TARGET_CPU_PPC */ + 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) { -#ifdef HOST_LITTLE_ENDIAN + +#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))); -#else -#ifdef TARGET_CPU_PPC +#elif defined(TARGET_CPU_PPC) return __lhbrx (nes6502_banks[address >> NES6502_BANKSHIFT], address & NES6502_BANKMASK); #else - uint32 x = - (uint32) * (uint16 *) (nes6502_banks[address >> NES6502_BANKSHIFT] + - (address & NES6502_BANKMASK)); - return (x << 8) | (x >> 8); -#endif /* TARGET_CPU_PPC */ + { + 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) + 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) +/* else if (address >= 0x6000) */ + else if (address >= 0x8000) { return bank_readbyte (address); + } /* check memory range handlers */ else { for (pmr = pmem_read; pmr->min_range != 0xFFFFFFFF; pmr++) { @@ -1260,6 +1396,7 @@ mem_write (uint32 address, uint8 value) { /* RAM */ if (address < 0x800) { + chk_mem_access (acc_ram + address, NES6502_WRITE_ACCESS); ram[address] = value; return; } @@ -1286,11 +1423,19 @@ 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; @@ -1312,8 +1457,12 @@ 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; @@ -1365,7 +1514,14 @@ 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; @@ -1398,9 +1554,10 @@ 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 */ BRK (); @@ -1641,7 +1798,7 @@ nes6502_execute (int remaining_cycles) break; case 0x38: /* SEC */ - NSF_SEC (); + SEC (); break; case 0x39: /* AND $nnnn,Y */ @@ -2392,25 +2549,18 @@ 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$ -** Revision 1.2 2007/10/08 17:46:44 thaytan -** * gst/librfb/rfbbuffer.c: (rfb_buffer_new_and_alloc): -** * gst/librfb/rfbbuffer.h: -** * gst/librfb/rfbdecoder.c: (rfb_socket_get_buffer): -** * gst/mpegvideoparse/mpegvideoparse.c: (gst_mpegvideoparse_chain): -** * gst/nsf/nes6502.c: (nes6502_execute): -** * gst/real/gstrealaudiodec.c: (gst_real_audio_dec_setcaps): -** * gst/real/gstrealvideodec.c: (open_library): -** * gst/real/gstrealvideodec.h: -** * gst/rtpmanager/gstrtpsession.c: (create_recv_rtp_sink), -** (create_recv_rtcp_sink), (create_send_rtp_sink): -** Fix compiler warnings shown by Forte. -** -** Revision 1.1 2006-07-13 15:07:28 wtay -** Based on patches by: Johan Dahlin <johan at gnome dot org> -** Ronald Bultje <rbultje at ronald dot bitfreak dot net> -** * configure.ac: +** Revision 1.3 2008/03/25 15:56:11 slomo +** Patch by: Andreas Henriksson <andreas at fatal dot set> ** * gst/nsf/Makefile.am: ** * gst/nsf/dis6502.h: ** * gst/nsf/fds_snd.c: @@ -2418,7 +2568,6 @@ nes6502_setdma (int cycles) ** * gst/nsf/fmopl.c: ** * gst/nsf/fmopl.h: ** * gst/nsf/gstnsf.c: -** * gst/nsf/gstnsf.h: ** * gst/nsf/log.c: ** * gst/nsf/log.h: ** * gst/nsf/memguard.c: @@ -2437,7 +2586,16 @@ nes6502_setdma (int cycles) ** * gst/nsf/vrc7_snd.h: ** * gst/nsf/vrcvisnd.c: ** * gst/nsf/vrcvisnd.h: -** Added NSF decoder plugin. Fixes 151192. +** Update our internal nosefart to nosefart-2.7-mls to fix segfaults +** on some files. Fixes bug #498237. +** Remove some // comments, fix some compiler warnings and use pow() +** instead of a slow, selfmade implementation. +** +** Revision 1.2 2003/05/01 22:34:19 benjihan +** New NSF plugin +** +** 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 |