summaryrefslogtreecommitdiff
path: root/contrib/nosefart/nes6502.c
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2011-03-20 14:25:40 +0000
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2011-03-20 14:25:40 +0000
commitced4b1666765715376058ea16669d18a4f3e68e6 (patch)
treedd8ca75cfc4f841b82f00ea7b24b849ee277577a /contrib/nosefart/nes6502.c
parent77aa841ba7f4249dceaea6470cb025f976a6e57a (diff)
parent5f74ef4b65a270a8b985917373bc0e219fa06ecd (diff)
downloadxine-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
Diffstat (limited to 'contrib/nosefart/nes6502.c')
-rw-r--r--contrib/nosefart/nes6502.c222
1 files changed, 200 insertions, 22 deletions
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