Diff of /src/libxineadec/nosefart/nes6502.c [e466b8] .. [87e73d]  Maximize  Restore

  Switch to side-by-side view

--- a/src/libxineadec/nosefart/nes6502.c
+++ b/src/libxineadec/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 *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)
 
-
-INLINE uint8 bank_readbyte(register uint32 address)
+#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, 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 @@
    /* RAM */
    if (address < 0x800)
    {
+     chk_mem_access(acc_ram + address, NES6502_WRITE_ACCESS);
       ram[address] = value;
       return;
    }
@@ -1258,11 +1412,19 @@
    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 @@
    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 @@
 
    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 @@
       /* 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 @@
    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.
+** Revision 1.2  2003/05/01 22:34:19  benjihan
+** New NSF plugin
 **
-** - Define the correct HOST_ENDIAN for SPARC
-** - remove unaligned memory accesses
-**
-** 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

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks