Page 1 of 1

Bit toggling detection (blargg mmc3 tests)

Posted: Sun Jun 10, 2012 2:18 pm
by Anes
I know, i know it's not an Emulator question, but i just wanted to know how to detect when a bit toggles in a variable in C.
I think i'm doing it well, but i wanted to know how YOU do it.
I have googled it you know, but i haven't found good info.

I ask since blarrg's mmc3 test rely in bit toggling at $2006.

Thxs

Posted: Sun Jun 10, 2012 2:26 pm
by Nessie

Code: Select all

bit_changed = (old ^ new) & bitmask;
new_bit_value = new & bitmask;

Posted: Sun Jun 10, 2012 3:15 pm
by Anes

Code: Select all

bit_changed = (old ^ new) & bitmask; 
new_bit_value = new & bitmask; 
Sorry for being to noob. I really don't get it :oops:
Shouldn't "old" be updated?
why "new_bit_value".
I think i need a programming class here.
Could you be more verbose?

Posted: Sun Jun 10, 2012 3:51 pm
by Dwedit
"old" is the previous value of the variable.
"new" is what you'll be setting the value to.
"bit_changed" is zero if the bit is the same, or nonzero if the bit has changed. You get this from XORing old and new, then masking with the bit mask.
"bitmask" is a variable that contains a single bit set somewhere. So if you want to look at bit 8, that's a value of 256, or (1 << 8).

So when you want to see if a variable has changed or not, you put in checking code every time you write to the variable.


But anyway, checking for PPU A12 changes is different, since PPU A12 changes all the time during rendering. The example code is a generic version of checking when a bit changes in a variable. In order for that kind of example code to work, you need to write your PPU code to work like Nintendulator's, where it actually sets a variable for the physical PPU address bus (different from the "PPU address value" from 2006) every time it does a fetch.

Posted: Sun Jun 10, 2012 4:04 pm
by Nessie
Your function could look something like this:

Code: Select all

void update_vram_address(unsigned int new_value)
{
  unsigned int old_value = vram_address;
  vram_address = new_value;
  if ((old_value ^ new_value) & 0x1000)
  {
    // A12 changed!
    bool new_a12_state = new & bitmask;
    a12_changed_to(new_a12_state);
  }
}
but as Dwedit says, you will have to call that function every time the VRAM address changes, i.e. before every memory fetch during rendering and whenever the $2006/$2007 registers are used.

Posted: Sun Jun 10, 2012 5:44 pm
by Zepper
I simply gave up about predicting the A12 state for MMC3. I'm rewriting my gfx engine.

Posted: Mon Jun 11, 2012 9:15 am
by Anes
Thanks much clear now, but i think i will not be predicting A12 line.
It's simply very hard (so Zepper don't feel bad :) ).

Wich is the simplest way to implement mmc3 clocking without predicting A12 state??

What im currently doing is clocking the counter at cc 256 including scanline -1, it doesn't work the best but it's a solution for me.