// cartridge.cpp: implementation of the CCartridge class.
//
//////////////////////////////////////////////////////////////////////

#include "cartridge.h"
#include "GBMachine.h"
#include <string.h> //for memXXX function

const _licensee_t g_licensee[] = {
    {"00","None"},
    {"01","Nintendo"},
    {"08","Capcom"},
    {"09","HOT.B Co., Ltd"},
    {"0A","Jaleco"},
    {"0B","Coconuts"},
    {"0C","Elite Systems/Coconuts"}, //?
    {"13","Electronic Arts"},
    {"18","Hudson soft"},
    {"19","B-AI/ITC Entertainment"}, //?
    {"1A","Yanoman"},
    {"1D","Clary"}, //?
    {"1F","Virgin Games/7-UP"}, //?
    {"20","KSS"}, //?
    {"22","Pow"}, //?
    {"24","PCM Complete"}, //?
    {"25","San-X"}, //?
    {"28","Kotobuki/Walt disney/Kemco Japan"}, //?
    {"29","Seta"},
    {"2L","Tamsoft"}, //?
    {"30","Infogrames/Viacom"}, //?
    {"31","Nintendo"}, //?
    {"32","Bandai"}, //?
    {"33","Ocean/Acclaim"}, //?
    {"34","Konami"}, //?
    {"35","Hector"},
    {"37","Taito"}, //?
    {"38","Kotobuki systems/Interactive TV ent/Capcom/Hudson"}, //?
    {"39","Telstar/Accolade/Banpresto"}, //?
    {"3C","Entertainment int./Empire/Twilight"}, //?
    {"3E","Gremlin Graphics/Chup Chup"}, //?
    {"41","UBI Soft"}, //?
    {"42","Atlus"}, //?
    {"44","Malibu"}, //?
    {"47","Spectrum Holobyte/Bullet Proof"}, //?
    {"46","Angel"}, //?
    {"49","Irem"},
    {"4A","Virgin"}, //?
    {"4D","Malibu (T-HQ)"},
    {"4F","U.S. Gold"},
    {"4J","Fox Interactive/Probe"}, //?
    {"4K","Time Warner"}, //?
    {"4S","Black Pearl (T-HQ)"},
    {"50","Absolute Entertainment"},
    {"51","Acclaim"},
    {"52","Activision"},
    {"53","American Sammy"}, //?
    {"54","Gametek/Infogenius Systems/Konami"}, //?
    {"55","Hi Tech Expressions/Park Place"},
    {"56","LJN. Toys Ltd"},
    {"57","Matchbox International"}, //?
    {"58","Mattel"}, //?
    {"59","Milton Bradley"}, //?
    {"5A","Mindscape"},
    {"5B","ROMStar"},
    {"5C","Taxan/Naxat soft"},
    {"5D","Williams/Tradewest/Rare"}, //?
    {"60","Titus"},
    {"61","Virgin Interactive"},
    {"64","LucasArts"}, //?
    {"67","Ocean"},
    {"69","Electronic Arts"},
    {"6E","Elite Systems"},
    {"6F","Electro brain"},
    {"70","Infogrames"},
    {"71","Interplay productions"},
    {"72","First Star Software/Broderbund"}, //?
    {"73","Sculptured software"}, //?
    {"75","The sales curve Ltd./SCi Entertainment Group"}, //?
    {"78","T-HQ Inc."},
    {"79","Accolade"},
    {"7A","Triffix Ent. Inc."}, //?
    {"7C","MicroProse/NMS"}, //?
    {"7D","Universal Interactive Studios"}, //?
    {"7F","Kotobuki Systems/Kemco"}, //?
    {"80","Misawa/NMS"}, //?
    {"83","LOZC/G.Amusements"}, //?
    {"86","Zener Works/Tokuna Shoten"}, //?
    {"87","Tsukuda Original"}, //?
    {"8B","Bullet-Proof software"},
    {"8C","Vic Tokai"},
    {"8E","Character soft/Sanrio/APE"}, //?
    {"8F","I'Max"},
    {"8M","CyberFront/Taito"}, //?
    {"91","Chun Soft"}, //?
    {"92","Video System"}, //?
    {"93","Bec/Tsuburava/Ocean/Acclaim"}, //?
    {"95","Varie"},
    {"96","Yonesawa/S'Pal"}, //?
    {"97","Kaneko"}, //?
    {"99","Pack-In-Video/ARC"},
    {"9A","Nihon Bussan"}, //?
    {"9B","Tecmo"},
    {"9C","Imagineer Co., Ltd"},
    {"9D","Banpresto"}, //?
    {"9F","Namco/Nova"}, //?
    {"A1","Hori electric"}, //?
    {"A2","Bandai"}, //?
    {"A4","Konami"},
    {"A6","Kawada"}, //?
    {"A7","Takara"},
    {"A9","Technos japan Corp."},
    {"AA","First Star software/Broderbund/dB soft"}, //?
    {"AC","Toei"},
    {"AD","TOHO Co., Ltd."}, //?
    {"AF","Namco hometek"},
    {"AG","Playmates/Shiny"}, //?
    {"AL","MediaFactory"}, //?
    {"B0","Acclaim/LJN"}, //?
    {"B1","Nexoft/ASCII"}, //?
    {"B2","Bandai"},
    {"B4","Enix"},
    {"B6","HAL"},
    {"B7","SNK (america)"},
    {"B9","Pony Canyon"},
    {"BA","Culture Brain"},
    {"BB","SunSoft"},
    {"BD","Sony Imagesoft"},
    {"BF","Sammy"},
    {"BL","MTO Inc."}, //?
    {"C0","Taito"},
    {"C2","Kemco"},
    {"C3","SquareSoft"},
    {"C4","Tokuma Shoten"},
    {"C5","Data East"},
    {"C6","Tonkin House"},
    {"C8","Koei"},
    {"C9","UPL Comp. Ltd"}, //?
    {"CA","Ultra games/konami"},
    {"CB","Vap Inc."},
    {"CC","USE Co., Ltd"}, //?
    {"CD","Meldac"},
    {"CE","FCI/Pony Canyon"},
    {"CF","Angel Co."},
    {"D0","Taito"}, //?
    {"D1","Sofel"},
    {"D2","Quest"},
    {"D3","Sigma Enterprises"},
    {"D4","Lenar/Ask kodansha"}, //?
    {"D6","Naxat soft"},
    {"D7","Copya system"}, //?
    {"D9","Banpresto"},
    {"DA","Tomy"},
    {"DB","Hiro/LJN"}, //?
    {"DD","NCS/Masiya"}, //?
    {"DE","Human"},
    {"DF","Altron"},
    {"DK","Kodansha"}, //?
    {"E0","KK DCE/Yaleco"}, //?
    {"E1","Towachiki"},
    {"E2","Yutaka"},
    {"E3","Varie"}, //?
    {"E4","T&E SOFT"}, //?
    {"E5","Epoch"},
    {"E7","Athena"},
    {"E8","Asmik"},
    {"E9","Natsume"},
    {"EA","King Records/A Wave"}, //?
    {"EB","Altus"},
    {"EC","Epic/Sony Records"},
    {"EE","IGS Corp"},
    {"EJ","Virgin"},
    {"F0","A Wave/Accolade"}, //?
    {"F3","Extreme Entertainment/Malibu int."}, //?
    {"FB","Psycnosis"}, //?
    {"FF","LJN"} //?
    };


//////////////////////////////////////////////////////////////////////////

CGBROMHeader::CGBROMHeader()
{
	m_cScrollNintendoGraphic;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCartridge::CCartridge()
{
	m_pMachine = NULL;

	m_pMBC = NULL;

	m_nRAMBanks = m_nROMBanks = 0;
}

CCartridge::~CCartridge()
{
	if(m_pMBC)
		delete m_pMBC;
}

void CCartridge::SetMachine(CGBMachine* pMachine)
{
	m_pMachine = pMachine;
}

const char* CCartridge::GetLicenseeName(u8 cHiCode, u8 u8LoCode)
{
    int i;
	int n = sizeof(g_licensee) / sizeof(_licensee_t);
    for(i = 0; i < n; i++)
    {
        if(g_licensee[i].code[0] == cHiCode && g_licensee[i].code[1] == u8LoCode)
            return g_licensee[i].name;
    }

	return "Unknown";
}

bool CCartridge::InsertRom(CGBROMHeader* pROMHeader)
{
	char sGameTitle[17];
	u8 cGBCFlag;
	//char sDestination[20];
	char* sDestination = NULL;
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW, "Checking ROM...\n");

	memcpy(sGameTitle, pROMHeader->m_cTitle, 15);

	sGameTitle[16] = '\0';
	cGBCFlag = pROMHeader->m_cGBCFlag;

	if(pROMHeader->m_cLicenseeCode_Old == 0x33) 
		sGameTitle[12] = '\0';

	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "Game Title: %s\n", sGameTitle);
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "GBC Flag: %02x\n", cGBCFlag);


	if(pROMHeader->m_cLicenseeCode_Old == 0x33) //new version
	{
        NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "Licensee (new): %s (%c%c)\n",
			GetLicenseeName(pROMHeader->m_cHiNibbleLic,pROMHeader->m_cLoNibbleLic),
			pROMHeader->m_cHiNibbleLic,pROMHeader->m_cLoNibbleLic);
	}
	else
	{
		char byte1 = ((pROMHeader->m_cLicenseeCode_Old >> 4) & 0x0F);
		byte1 += (byte1 < 10) ? 0x30 : (0x41 - 10);
		char byte2 = (pROMHeader->m_cLicenseeCode_Old & 0x0F);
		byte2 += (byte2 < 10) ? 0x30 : (0x41 - 10);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "Licensee (old): %s (%02x)\n",
			GetLicenseeName(byte1,byte2), pROMHeader->m_cLicenseeCode_Old);
	}

	switch(pROMHeader->m_cDestinationCode)
	{
	case 0:
		sDestination = "Japanese";
		break;
	case 1:
		sDestination = "Non-Japanese";
		break;
	default:
		sDestination = "Unknown";
	}
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "Destination %s:\n", sDestination);


	//m_pMachine->DisableAllHW();

	u32 dwEnableHW = 0;
	//GameBoy COLOR
	if(pROMHeader->m_cGBCFlag & (0x80))
	{
		if(pROMHeader->m_cGBCFlag == 0xC0)//GBC only
		{
			dwEnableHW |= ENABLE_GBC;
		}
		else if(pROMHeader->m_cGBCFlag == 0x80) //Can use a normal GB too
		{
			dwEnableHW |= ENABLE_GBC;
			dwEnableHW |= ENABLE_GB;
		}
		else //Unknown
		{
			dwEnableHW |= ENABLE_GBC;
			dwEnableHW |= ENABLE_GB;
			
			NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "[!]Unknown GBC flag...\n");
		}
	}
	else //GB
	{
		dwEnableHW |= ENABLE_GB;
	}
	
	//SGB
	if(pROMHeader->m_SGBFlag == 0x03 && pROMHeader->m_cLicenseeCode_Old == 0x33)
	{
		dwEnableHW |= ENABLE_SGB;
	}

	if(g_configinfo.m_HWType == HW_AUTO)
	{
		if(dwEnableHW & ENABLE_GBC)
			g_configinfo.m_HWType = HW_GBC;
		else if(dwEnableHW & ENABLE_SGB)
			g_configinfo.m_HWType = HW_SGB;
		else
			g_configinfo.m_HWType = HW_GB;

		g_configinfo.m_HWType = HW_GB;
	}


	//Load Inner ROM
    if(g_configinfo.m_bLoadInnerROM)
    {
        //Load boot rom if any...
        char * boot_rom_filename = NULL;
        switch(g_configinfo.m_HWType)
        {
		case HW_GB: 
			boot_rom_filename = DMG_ROM_FILENAME; 
			break;
		case HW_GBP: 
			boot_rom_filename = MGB_ROM_FILENAME; 
			break;
		case HW_SGB: 
			boot_rom_filename = SGB_ROM_FILENAME; 
			break;
		case HW_SGB2: 
			boot_rom_filename = SGB2_ROM_FILENAME; 
			break;
		case HW_GBC: 
			boot_rom_filename = CGB_ROM_FILENAME; 
			break;
		case HW_GBA: 
			boot_rom_filename = AGB_ROM_FILENAME; 
			break;
        }
		
		if(boot_rom_filename)
#if !NMGB_INTEGRATE_INNERROM
			g_configinfo.m_sInnerRomFile = boot_rom_filename;
#else
			g_configinfo.m_sInnerRomFile = (char*)DMG_ROM_bin;
#endif
			
    }

	//@@@@@@@@@@
	if(g_pGameBoy)
	{
		delete g_pGameBoy;
		g_pGameBoy = NULL;
	}
	//@@@@@@@@@@

	switch(g_configinfo.m_HWType)
	{
	case HW_GB:
		g_pGameBoy = new CGBMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in GB mode...\n");
		break;
	case HW_GBP:
		g_pGameBoy = new CGBPMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in GBP mode...\n");
		break;
	case HW_GBC:
		g_pGameBoy = new CGBCMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in GBC mode...\n");
		break;
		break;
	case HW_SGB:
		g_pGameBoy = new CSGBMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in SGB mode...\n");
		break;
	case HW_SGB2:
		g_pGameBoy = new CSGBMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in SGB2 mode...\n");
		break;
	case HW_GBA:
		g_pGameBoy = new CGBCMachine(g_configinfo.m_sInnerRomFile);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW,"Loading in GBA mode...\n");
	default: //Should never happen
		return false;
	}

	g_pGameBoy->SetHWType(g_configinfo.m_HWType);//@@@@@@@@@@@@@@
	m_pMachine = g_pGameBoy;


	//CARTRIDGE TYPE
	//////////////////////////////////////////////////////////////////////////
	if(m_pMBC)
	{
		delete m_pMBC;
		m_pMBC = NULL;
	}
	//////////////////////////////////////////////////////////////////////////
	int mbc_banks = 0;
	switch(pROMHeader->m_cCartridgeType)
	{
	case 0x00: //ROM ONLY
		m_pMBC = new CMBCNone(m_pMachine->GetMemory());
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"ROM initialized!");
		break;
	case 0x01: //MBC1
		m_pMBC = new CMBC1(m_pMachine->GetMemory());
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC1 initialized!");
		break;
	case 0x02: //MBC1+RAM
		m_pMBC = new CMBC1(m_pMachine->GetMemory(),true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC1+RAM initialized!");
		break;
	case 0x03: //MBC1+RAM+BATTERY
		m_pMBC = new CMBC1(m_pMachine->GetMemory(),true,true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC1+RAM+BATTERY initialized!");
		break;
	case 0x05: //MBC2
		m_pMBC = new CMBC2(m_pMachine->GetMemory());
		mbc_banks = 1;
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC2 initialized!");
		break;
	case 0x06: //MBC2+BATTERY
		m_pMBC = new CMBC2(m_pMachine->GetMemory());
		mbc_banks = 1;
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC2+BATTERY initialized!");
		break;
	case 0x08: //ROM+RAM
		m_pMBC = new CMBCNone(m_pMachine->GetMemory());
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"ROM+RAM initialized!");
		break;
	case 0x09: //ROM+RAM+BATTERY
		m_pMBC = new CMBCNone(m_pMachine->GetMemory());
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"ROM+RAM+BATTERY initialized!");
		break;
	case 0x19: //MBC5
		m_pMBC = new CMBC5(m_pMachine->GetMemory());
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 initialized!");
		break;
	case 0x1A: //MBC5+RAM
		m_pMBC = new CMBC5(m_pMachine->GetMemory(),false,true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 + RAM initialized!");
		break;
	case 0x1B: //MBC5+RAM+BATTERY
		m_pMBC = new CMBC5(m_pMachine->GetMemory(),false,true,true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 + RAM + BATTERY initialized!");
		break;
	case 0x1C: //MBC5+RUMBLE
		m_pMBC = new CMBC5(m_pMachine->GetMemory(),true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 + RUMBLE initialized!");
		break;
	case 0x1D: //MBC5+RUMBLE+RAM
		m_pMBC = new CMBC5(m_pMachine->GetMemory(),true,true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 + RUMBLE + RAM initialized!");
		break;
	case 0x1E: //MBC5+RUMBLE+RAM+BATTERY
		m_pMBC = new CMBC5(m_pMachine->GetMemory(),true,true,true);
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE,"MBC5 + RUMBLE + RAM + BATTERY initialized!");
		break;
	default:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"[!]Now %02x CartridgeType is not supported!\n", pROMHeader->m_cCartridgeType);
		break;
	}
	m_pMachine->SetMBC(m_pMBC);

	//RAM
	switch(pROMHeader->m_cRAMSize)
	{
	case 0x00: 
		m_nRAMBanks = 0; 
		break;
	case 0x01: //2KB
		m_nRAMBanks = 1; 
		break; 
	case 0x02: //8KB
		m_nRAMBanks = 1; 
		break; 
	case 0x03: //4 * 8KB
		m_nRAMBanks = 4; 
		break; 
	case 0x04: //16 * 8KB
		m_nRAMBanks = 16; 
		break; 
	default:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED, "[!]RAM SIZE UNKNOWN: %02x\n", pROMHeader->m_cRAMSize);
		return 0;
	}
	m_nRAMBanks = m_nRAMBanks > mbc_banks ? m_nRAMBanks : mbc_banks;
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "RAM Banks: %d\n", m_nRAMBanks);
	m_pMachine->GetMemory()->RAMBankNum(m_nRAMBanks);
	

	//ROM
	switch(pROMHeader->m_cROMSize)
	{
	case 0x00: 
		m_nROMBanks = 2; 
		break;
	case 0x01: 
		m_nROMBanks = 4; 
		break;
	case 0x02: 
		m_nROMBanks = 8; 
		break;
	case 0x03: 
		m_nROMBanks = 16; 
		break;
	case 0x04: 
		m_nROMBanks = 32; 
		break;
	case 0x05: 
		m_nROMBanks = 64; 
		break;
	case 0x06: 
		m_nROMBanks = 128; 
		break;
	case 0x07: 
		m_nROMBanks = 256; 
		break;
	case 0x08: 
		m_nROMBanks = 512; 
		break;
		//	case 0x52: m_nROMBanks = 72; break; // After the general checksum, this
		//	case 0x53: m_nROMBanks = 80; break; // is changed to 128 to avoid
		//	case 0x54: m_nROMBanks = 96; break; // problems...
		//	I've never seen a game with 0x52, 0x53 or 0x54 in its header.
	default:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED, "[!]ROM SIZE UNKNOWN: %02x\n", pROMHeader->m_cROMSize);
		return 0;
	}
	m_pMachine->GetMemory()->ROMBankNum(m_nROMBanks);
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_WHITE, "ROM Banks: %d\n", m_nROMBanks);


	//Checksums
	
	//(1)Header
	u32 sum = 0;
	u32 count;
	u8* pData = (u8*)pROMHeader;
	for(count = 0x0134; count <= 0x014C; count ++)
		sum = sum - pData[count] - 1;
	
	sum &= 0xFF;
	
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW, "Header checksum: %02x - Obtained: %02x\n", pROMHeader->m_cHeaderCheckSum, sum);
	
	if(pROMHeader->m_cHeaderCheckSum != sum)
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED, "[!]INCORRECT! - Maybe a bad dump?\n[!]Game wouldn't work in a real GB.\n");
	
	//(2)Global
	/*
	u32 size = m_nROMBanks * 16 * 1024;
	sum = 0;
	for(count = 0; count < size; count ++)
		sum += (u32)pData[count];
	
	sum -= pROMHeader->m_cGlobalCheckSum & 0xFF; //Checksum bytes not included
	sum -= (pROMHeader->m_cGlobalCheckSum>>8) & 0xFF;
	
	sum &= 0xFFFF;
	sum = ((sum>>8)&0x00FF) | ((sum<<8)&0xFF00);
	
	NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW, "Global checksum: %04x - Obtained: %04x\n", pROMHeader->m_cGlobalCheckSum, sum);
	
	if(pROMHeader->m_cGlobalCheckSum != sum)
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED, "[!]INCORRECT! - Maybe a bad dump?\n");
	*/
	bool bcomp = memcmp(CGBMachine::m_cNintendoLogo, pROMHeader->m_cScrollNintendoGraphic, sizeof(CGBMachine::m_cNintendoLogo)) == 0;

    if(bcomp)
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_YELLOW, "Checking Nintendo logo...Correct!\n ");
	else
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED, "[!]Checking Nintendo logo...INCORRECT! - Maybe a bad dump?\n[!]Game wouldn't work in a real GB.\n");

	return true;
}

bool CCartridge::LoadRomFile(const char* sFilePath)
{
#if !NMGB_INTEGRATE_ROM
	if(!sFilePath)
		return false;
	FILE* fp = fopen(sFilePath,"rb");
	if(!fp)
	{
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Can not open the rom file: %s\n",sFilePath);
		return false;
	}
#endif
	g_configinfo.m_sROMFile = sFilePath;

	CGBROMHeader	rom_header;
	//fseek(fp, 0x100, SEEK_SET);
#if !NMGB_INTEGRATE_ROM
	fread(&rom_header, sizeof(rom_header), 1, fp);

	fclose(fp);
#else
	memcpy(&rom_header,sFilePath,sizeof(rom_header));
#endif
	InsertRom(&rom_header);

	return true;
}

bool CCartridge::IsRumbleEnable()
{
	EMBCType mbctype = m_pMBC->MBCType();
	if(mbctype == MBC5 || mbctype == MBC_RUMBLE)
		return ((CMBC5*)m_pMBC)->IsRumbleEnable();

	return false;
}
