//////////////////////////////////////////////////////////////////////////
// Mapper190  Nintendo MMC3                                             //
//////////////////////////////////////////////////////////////////////////
void	Mapper190::Reset()
{
	SetPROM_32K_Bank( 0, 1, PROM_8K_SIZE-2, PROM_8K_SIZE-1 );

//	DWORD	crc = nes->rom->GetPROM_CRC();
//	if( crc == 0x6F3D187A ) {
//		Temp_Buf=0;	//Kof96
//	} else {
//		Temp_Buf=1;	//ST97
//	}

	irq_enable = 0;
	irq_counter = 0;
	cbase = 0;		/* PowerOn OR RESET : cbase=0 */
	mp190_lcchk = 0;	/* PowerOn OR RESET */
	mp190_lcmd = 1;
}

void	Mapper190::WriteLow( WORD addr, BYTE data )
{
	/* For Initial Copy Protect check (KOF'96) */
	if( addr == 0x5000 ) {
		mp190_lcmd = data;
		switch( data ) {
			case	0xE0:
				SetPROM_32K_Bank( 0 );
				break;
			case	0xEE:
				SetPROM_32K_Bank( 3 );
				break;
		}
	}
	if( (addr==0x5001) && (mp190_lcmd==0x00) ) {
		 SetPROM_32K_Bank( 7 );
	}
	if( addr == 0x5080 ) {
		switch( data ) {
			case 0x1:lowoutdata=0x83;break;
			case 0x2:lowoutdata=0x42;break;
			case 0x3:lowoutdata=0x00;break;
		}
	}
	CPU_MEM_BANK[addr>>13][addr&0x1FFF] = data;
}

BYTE	Mapper190::ReadLow( WORD addr )
{
	switch( addr ) {
		case	0x5000:
			return	lowoutdata;
		default:
			return	CPU_MEM_BANK[addr>>13][addr&0x1FFF];
	}
}

void	Mapper190::Write( WORD addr, BYTE data )
{
	switch( addr & 0xE003 ) {
		case	0x8000:
			mp190_cmd = data;
			if( mp190_cmd & 0x80 )
				cbase = 1;
			else
				cbase = 0;
			break;
		case	0x8003:	/* for Street Fighter Zero 2 '97 */
			mp190_lcchk = data;
			switch( data ) {
				case	0x28:
					SetPROM_8K_Bank( 4, 0x1F );
					SetPROM_8K_Bank( 5, 0x1F );
					SetPROM_8K_Bank( 6, 0x17 );
					SetPROM_8K_Bank( 7, 0x1F );
					break;
				case	0x2A:
					 SetPROM_8K_Bank( 4, 0x1F );
					 SetPROM_8K_Bank( 5, 0x0F );
					 SetPROM_8K_Bank( 6, 0x17 );
					 SetPROM_8K_Bank( 7, 0x1F );
					 break;
				case 0x06:
					 SetPROM_8K_Bank( 4, 0x1E );
					 SetPROM_8K_Bank( 5, 0x1F );
					 SetPROM_8K_Bank( 6, 0x1F );
					 SetPROM_8K_Bank( 7, 0x1F );
					 break;	
			}
			break;
		case	0x8001:
			if( (mp190_lcchk==0x6) || (mp190_lcmd==0x0) ) {
				switch( mp190_cmd & 0x07 ) {
					case	0:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(0,data+0x100);
							SetVROM_1K_Bank(1,data+0x101);
						} else {
							SetVROM_1K_Bank(4,data+0x100);
							SetVROM_1K_Bank(5,data+0x101);
						}
						break;
					case	1:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(2,data+0x100);
							SetVROM_1K_Bank(3,data+0x101);
						} else {
							SetVROM_1K_Bank(6,data+0x100);
							SetVROM_1K_Bank(7,data+0x101);
						}
						break;
					case	2:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(4,data);
						} else {
							SetVROM_1K_Bank(0,data);
						}
						break;
					case	3:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(5,data);
						} else {
							SetVROM_1K_Bank(1,data);
						}
						break;
					case	4:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(6,data);
						} else {
							SetVROM_1K_Bank(2,data);
						}
						break;
					case	5:
						if( cbase == 0 ) {
							SetVROM_1K_Bank(7,data);
						} else {
							SetVROM_1K_Bank(3,data);
						}
						break;
					case	6:
						data=data&((PROM_8K_SIZE*2)-1);
						if( mp190_lcmd & 0x40 ) {
							SetPROM_8K_Bank(6,data);
							SetPROM_8K_Bank(4,(PROM_8K_SIZE-1)*2);
						} else {
							SetPROM_8K_Bank(4,data);
							SetPROM_8K_Bank(6,(PROM_8K_SIZE-1)*2);
						}
						break;
					case	7:
						data=data&((PROM_8K_SIZE*2)-1);
						if( mp190_lcmd & 0x40 ) {
							SetPROM_8K_Bank(5,data);
							SetPROM_8K_Bank(4,(PROM_8K_SIZE-1)*2);
						} else {
							SetPROM_8K_Bank(5,data);
							SetPROM_8K_Bank(6,(PROM_8K_SIZE-1)*2);
						}
						break;
				}
			}
			break;
		case	0xA000:
		        if( (data&0x1) == 0x1 )
				SetVRAM_Mirror( VRAM_HMIRROR );
			else
				SetVRAM_Mirror( VRAM_VMIRROR );
		        break;
		case	0xA001:
			break;
		case	0xC000:
			irq_counter = data-1;
			break;
		case	0xC001:
			irq_latch = data-1;
			break;
		case	0xC002:
			irq_counter = data;
			break;
		case	0xC003:
			irq_latch = data;
			break;
		case	0xE000:
			irq_counter = irq_latch;
			irq_enable = 0;
			nes->cpu->ClrIRQ( IRQ_MAPPER );
			break;
		case	0xE001:
			irq_enable = 1;
			break;
		case	0xE002:
			irq_counter = irq_latch;
			irq_enable = 0;
			nes->cpu->ClrIRQ( IRQ_MAPPER );
			break;
		case	0xE003:
			irq_enable = 1;
			irq_counter = irq_counter;
			break;
	}
}

void	Mapper190::HSync( INT scanline )
{
	if( (scanline >= 0 && scanline <= 239) ) {
		if( nes->ppu->IsDispON() ) {
			if( irq_enable ) {
				if( !(irq_counter--) ) {
//					nes->cpu->IRQ_NotPending();
					nes->cpu->SetIRQ( IRQ_MAPPER );
				}
			}
		}
	}
}

void	Mapper190::SaveState( LPBYTE p )
{
	p[0] = irq_enable;
	p[1] = irq_counter;
	p[2] = irq_latch;

	p[3] = cbase;
	p[4] = mp190_lcchk;
	p[5] = mp190_lcmd;
	p[6] = mp190_cmd;
	p[7] = lowoutdata;
}

void	Mapper190::LoadState( LPBYTE p )
{
	irq_enable  = p[0];
	irq_counter = p[1];
	irq_latch   = p[2];

	cbase       = p[3];
	mp190_lcchk = p[4];
	mp190_lcmd  = p[5];
	mp190_cmd   = p[6];
	lowoutdata  = p[7];
}
