Mapper 209 (JY Company) and MMC2 mode

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
zeroone
Posts: 929
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Mapper 209 (JY Company) and MMC2 mode

Post by zeroone » Tue Jan 03, 2017 12:09 pm

The wiki never mentions MMC2 mode, seen in the Nintendulator snippet below (and other emulator sources):

Code: Select all

int	MAPINT	PPURead (int Bank, int Addr)
{
	if (IRQenabled && ((IRQmode & 0x3) == 3))
		IRQcount();
	int result = _PPURead[Bank](Bank, Addr);
	if (MMC2Mode)
	{
		if (Bank == 3)
		{
			if ((Addr & 0x3F8) == 0x3D8)
				LatchState[0] = 0;
			else if ((Addr & 0x3F8) == 0x3E8)
				LatchState[0] = 2;
			else	return result;
			if ((BankMode & 0x18) == 0x08)
				SyncCHR();
		}
		else if (Bank == 7)
		{
			if ((Addr & 0x3F8) == 0x3D8)
				LatchState[1] = 4;
			else if ((Addr & 0x3F8) == 0x3E8)
				LatchState[1] = 6;
			else	return result;
			if ((BankMode & 0x18) == 0x08)
				SyncCHR();
		}
	}
	return result;
}
The following games will not work when that logic is omitted:

Power Rangers III (Pirate).7z <Power Rangers III (Unl) [!].nes>
Power Rangers III (Pirate).7z <Power Rangers IV (Unl) [!].nes>
Punch-Out!!.7z <Mike Tyson's Punch-Out!! (Unl) [!].nes>

lidnariq
Posts: 8769
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Mapper 209 (JY Company) and MMC2 mode

Post by lidnariq » Tue Jan 03, 2017 12:57 pm

Would you be willing to edit the [[JY Company]] article to include these findings? After having read the Nintendulator and Nestopia sources I wasn't certain I understood how the CHR registers corresponded to A/B.

User avatar
zeroone
Posts: 929
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Mapper 209 (JY Company) and MMC2 mode

Post by zeroone » Tue Jan 03, 2017 1:18 pm

I am not 100% sure myself. I could add something like, VRAM reads affect bank assignment somewhat similar to MMC2 using the following logic, followed by a pseudo-code translation of one of those sources. I don't understand where information like this comes from. How do all the emulator sources have this bit of extra logic?

User avatar
Quietust
Posts: 1492
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Mapper 209 (JY Company) and MMC2 mode

Post by Quietust » Tue Jan 03, 2017 6:56 pm

I apparently added support for that back in January 2011, and I don't recall where I got it from (nor did I mention it in my commit message) - it's very possible I got it from another emulator such as Nestopia.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

lidnariq
Posts: 8769
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Mapper 209 (JY Company) and MMC2 mode

Post by lidnariq » Tue Jan 03, 2017 7:09 pm

Oldest thing I can easily find is support in the initial commit of FCEUmm to SVN, on 2006 June 16. It was also in the initial commit for FCEUX SVN a month later. There's no support for any of the family in FCEU-0.98

User avatar
zeroone
Posts: 929
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Mapper 209 (JY Company) and MMC2 mode

Post by zeroone » Fri Jan 06, 2017 3:51 pm

I noticed another discrepancy. From the wiki:

Code: Select all

                       $6000        $8000   $A000   $C000   $E000  
                +-----------------+-------------------------------+
 PRG Mode %000  |  ($8003 * 4)+3  |             { -1}             |
                +-----------------+-------------------------------+
 PRG Mode %001  |  ($8003 * 2)+1  |     $8001     |     { -1}     |
                +-----------------+---------------+---------------+
 PRG Mode %010  |      $8003      | $8000 | $8001 | $8002 | { -1} |
                +-----------------+-------+-------+-------+-------+
 PRG Mode %011  |      $8003      | $8000 | $8001 | $8002 | { -1} |  *BIT REVERSE*
                +-----------------+-------------------------------+
 PRG Mode %100  |  ($8003 * 4)+3  |             $8003             |
                +-----------------+-------------------------------+
 PRG Mode %101  |  ($8003 * 2)+1  |     $8001     |     $8003     |
                +-----------------+---------------+---------------+
 PRG Mode %110  |      $8003      | $8000 | $8001 | $8002 | $8003 |
                +-----------------+-------+-------+-------+-------+
 PRG Mode %111  |      $8003      | $8000 | $8001 | $8002 | $8003 |  *BIT REVERSE*
                +-----------------+-------+-------+-------+-------+
The final bank in program modes 0, 1, 2 and 3 is fixed to -1. But, according to FCEUX's source, it may not be that simple:

Code: Select all

static void tekprom(void)
{
  uint32 bankmode=((tkcom[3]&6)<<5);
  switch(tkcom[0]&7)
  {
    case 00: if(tkcom[0]&0x80)
               setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
             setprg32(0x8000,0x0F|((tkcom[3]&6)<<3));
             break;
    case 01: if(tkcom[0]&0x80)
               setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
             setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
             setprg16(0xC000,0x1F|((tkcom[3]&6)<<4));
             break;
    case 03: // bit reversion
    case 02: if(tkcom[0]&0x80)
               setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
             setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
             setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
             setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
             setprg8(0xe000,0x3F|bankmode);
             break;
    case 04: if(tkcom[0]&0x80)
               setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
             setprg32(0x8000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3));
             break;
    case 05: if(tkcom[0]&0x80)
               setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
             setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
             setprg16(0xC000,(prgb[3]&0x1F)|((tkcom[3]&6)<<4));
             break;
    case 07: // bit reversion
    case 06: if(tkcom[0]&0x80)
               setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
             setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
             setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
             setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
             setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
             break;
  }
}
tkcom[3] corresponds to:

Code: Select all

$D003:  [M.BH HHHH]
      M = Mirror CHR (very strange, see below)
      B = CHR Block mode (0=enabled, 1=disabled)
      H = CHR Block (when in block mode)
The code seems to suggest that CHR block register affects PRG banking.

Edit: Also, I do not see an indication that FCEUX is doing the bit reversals elsewhere.

Edit 2: Check out the following ROMs:

Multi-Game Pirate Carts.7z <45-in-1 (JY-120A) (Unl) [b1].nes>
Multi-Game Pirate Carts.7z <45-in-1 (JY-120A) (Unl) [!].unf>

Both of these are the same in 2 different file formats. It's a mapper 90 multi-game. They work in FCEUX and Nestopia only, but I have yet to figure out how and it might be related to those undocumented registers.

Edit 3:

Code: Select all

 Funky Mode:
 
 When 'F' in $C001 is clear, $C007 is ignored.  When set, exact operation is unknown.  It appears to funkify
 the prescaler.  $C007 containing any value other than $FF will result in the IRQ counter not being clocked at
 all... and $FF will result in the prescaler dividing by strange amounts (sometimes 8?  sometimes 12?
 sometimes 257?).  Details are unknown.  Fortunately, no games use this funky mode.
FCEUX implements it:

Code: Select all

    case 07: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n");
             //     else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n");
             //     else FCEU_printf("Counter Stopped\n");
             IRQPreSize=V;break;

Post Reply